diff --git a/.github/workflows/submit.yml b/.github/workflows/submit.yml index 910d4352510c2f696c5c809db17f606451e38a8a..93dd4e4b9f08333a89f8e5a36a63ff4dc1afb9b4 100644 --- a/.github/workflows/submit.yml +++ b/.github/workflows/submit.yml @@ -12,6 +12,10 @@ on: required: true default: "Linux additional (hotspot only), Linux x64, Linux x86, Windows aarch64, Windows x64, macOS x64" +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + jobs: prerequisites: name: Prerequisites @@ -19,6 +23,7 @@ jobs: outputs: should_run: ${{ steps.check_submit.outputs.should_run }} bundle_id: ${{ steps.check_bundle_id.outputs.bundle_id }} + jdk_version: ${{ steps.check_jdk_versions.outputs.jdk_version }} platform_linux_additional: ${{ steps.check_platforms.outputs.platform_linux_additional }} platform_linux_x64: ${{ steps.check_platforms.outputs.platform_linux_x64 }} platform_linux_x86: ${{ steps.check_platforms.outputs.platform_linux_x86 }} @@ -66,6 +71,23 @@ jobs: run: "echo '${{ steps.check_deps.outputs.dependencies }}'" if: steps.check_submit.outputs.should_run != 'false' + - name: Determine full JDK versions + id: check_jdk_versions + shell: bash + run: | + FEATURE=${{ fromJson(steps.check_deps.outputs.dependencies).DEFAULT_VERSION_FEATURE }} + INTERIM=${{ fromJson(steps.check_deps.outputs.dependencies).DEFAULT_VERSION_INTERIM }} + UPDATE=${{ fromJson(steps.check_deps.outputs.dependencies).DEFAULT_VERSION_UPDATE }} + if [ "x${UPDATE}" != "x0" ]; then + V=${FEATURE}.${INTERIM}.${UPDATE} + elif [ "x${INTERIM}" != "x0" ]; then + V={FEATURE}.${INTERIM} + else + V=${FEATURE} + fi + echo "::set-output name=jdk_version::${V}" + if: steps.check_submit.outputs.should_run != 'false' + - name: Determine the jtreg ref to checkout run: "echo JTREG_REF=jtreg-${{ fromJson(steps.check_deps.outputs.dependencies).JTREG_VERSION }}+${{ fromJson(steps.check_deps.outputs.dependencies).JTREG_BUILD }} >> $GITHUB_ENV" if: steps.check_submit.outputs.should_run != 'false' @@ -121,7 +143,7 @@ jobs: artifact: -debug env: - JDK_VERSION: "${{ fromJson(needs.prerequisites.outputs.dependencies).DEFAULT_VERSION_FEATURE }}" + JDK_VERSION: "${{ needs.prerequisites.outputs.jdk_version }}" BOOT_JDK_VERSION: "${{ fromJson(needs.prerequisites.outputs.dependencies).BOOT_JDK_VERSION }}" BOOT_JDK_FILENAME: "${{ fromJson(needs.prerequisites.outputs.dependencies).LINUX_X64_BOOT_JDK_FILENAME }}" BOOT_JDK_URL: "${{ fromJson(needs.prerequisites.outputs.dependencies).LINUX_X64_BOOT_JDK_URL }}" @@ -249,7 +271,7 @@ jobs: artifact: -debug env: - JDK_VERSION: "${{ fromJson(needs.prerequisites.outputs.dependencies).DEFAULT_VERSION_FEATURE }}" + JDK_VERSION: "${{ needs.prerequisites.outputs.jdk_version }}" BOOT_JDK_VERSION: "${{ fromJson(needs.prerequisites.outputs.dependencies).BOOT_JDK_VERSION }}" BOOT_JDK_FILENAME: "${{ fromJson(needs.prerequisites.outputs.dependencies).LINUX_X64_BOOT_JDK_FILENAME }}" BOOT_JDK_URL: "${{ fromJson(needs.prerequisites.outputs.dependencies).LINUX_X64_BOOT_JDK_URL }}" @@ -431,7 +453,7 @@ jobs: gnu-arch: powerpc64le env: - JDK_VERSION: "${{ fromJson(needs.prerequisites.outputs.dependencies).DEFAULT_VERSION_FEATURE }}" + JDK_VERSION: "${{ needs.prerequisites.outputs.jdk_version }}" BOOT_JDK_VERSION: "${{ fromJson(needs.prerequisites.outputs.dependencies).BOOT_JDK_VERSION }}" BOOT_JDK_FILENAME: "${{ fromJson(needs.prerequisites.outputs.dependencies).LINUX_X64_BOOT_JDK_FILENAME }}" BOOT_JDK_URL: "${{ fromJson(needs.prerequisites.outputs.dependencies).LINUX_X64_BOOT_JDK_URL }}" @@ -578,7 +600,7 @@ jobs: # Reduced 32-bit build uses the same boot JDK as 64-bit build env: - JDK_VERSION: "${{ fromJson(needs.prerequisites.outputs.dependencies).DEFAULT_VERSION_FEATURE }}" + JDK_VERSION: "${{ needs.prerequisites.outputs.jdk_version }}" BOOT_JDK_VERSION: "${{ fromJson(needs.prerequisites.outputs.dependencies).BOOT_JDK_VERSION }}" BOOT_JDK_FILENAME: "${{ fromJson(needs.prerequisites.outputs.dependencies).LINUX_X64_BOOT_JDK_FILENAME }}" BOOT_JDK_URL: "${{ fromJson(needs.prerequisites.outputs.dependencies).LINUX_X64_BOOT_JDK_URL }}" @@ -714,7 +736,7 @@ jobs: # Reduced 32-bit build uses the same boot JDK as 64-bit build env: - JDK_VERSION: "${{ fromJson(needs.prerequisites.outputs.dependencies).DEFAULT_VERSION_FEATURE }}" + JDK_VERSION: "${{ needs.prerequisites.outputs.jdk_version }}" BOOT_JDK_VERSION: "${{ fromJson(needs.prerequisites.outputs.dependencies).BOOT_JDK_VERSION }}" BOOT_JDK_FILENAME: "${{ fromJson(needs.prerequisites.outputs.dependencies).LINUX_X64_BOOT_JDK_FILENAME }}" BOOT_JDK_URL: "${{ fromJson(needs.prerequisites.outputs.dependencies).LINUX_X64_BOOT_JDK_URL }}" @@ -865,7 +887,7 @@ jobs: artifact: -debug env: - JDK_VERSION: "${{ fromJson(needs.prerequisites.outputs.dependencies).DEFAULT_VERSION_FEATURE }}" + JDK_VERSION: "${{ needs.prerequisites.outputs.jdk_version }}" BOOT_JDK_VERSION: "${{ fromJson(needs.prerequisites.outputs.dependencies).BOOT_JDK_VERSION }}" BOOT_JDK_FILENAME: "${{ fromJson(needs.prerequisites.outputs.dependencies).WINDOWS_X64_BOOT_JDK_FILENAME }}" BOOT_JDK_URL: "${{ fromJson(needs.prerequisites.outputs.dependencies).WINDOWS_X64_BOOT_JDK_URL }}" @@ -953,7 +975,7 @@ jobs: artifact: -debug env: - JDK_VERSION: "${{ fromJson(needs.prerequisites.outputs.dependencies).DEFAULT_VERSION_FEATURE }}" + JDK_VERSION: "${{ needs.prerequisites.outputs.jdk_version }}" BOOT_JDK_VERSION: "${{ fromJson(needs.prerequisites.outputs.dependencies).BOOT_JDK_VERSION }}" BOOT_JDK_FILENAME: "${{ fromJson(needs.prerequisites.outputs.dependencies).WINDOWS_X64_BOOT_JDK_FILENAME }}" BOOT_JDK_URL: "${{ fromJson(needs.prerequisites.outputs.dependencies).WINDOWS_X64_BOOT_JDK_URL }}" @@ -1104,7 +1126,7 @@ jobs: artifact: -debug env: - JDK_VERSION: "${{ fromJson(needs.prerequisites.outputs.dependencies).DEFAULT_VERSION_FEATURE }}" + JDK_VERSION: "${{ needs.prerequisites.outputs.jdk_version }}" BOOT_JDK_VERSION: "${{ fromJson(needs.prerequisites.outputs.dependencies).BOOT_JDK_VERSION }}" BOOT_JDK_FILENAME: "${{ fromJson(needs.prerequisites.outputs.dependencies).WINDOWS_X64_BOOT_JDK_FILENAME }}" BOOT_JDK_URL: "${{ fromJson(needs.prerequisites.outputs.dependencies).WINDOWS_X64_BOOT_JDK_URL }}" @@ -1279,7 +1301,7 @@ jobs: artifact: -debug env: - JDK_VERSION: "${{ fromJson(needs.prerequisites.outputs.dependencies).DEFAULT_VERSION_FEATURE }}" + JDK_VERSION: "${{ needs.prerequisites.outputs.jdk_version }}" BOOT_JDK_VERSION: "${{ fromJson(needs.prerequisites.outputs.dependencies).BOOT_JDK_VERSION }}" BOOT_JDK_FILENAME: "${{ fromJson(needs.prerequisites.outputs.dependencies).MACOS_X64_BOOT_JDK_FILENAME }}" BOOT_JDK_URL: "${{ fromJson(needs.prerequisites.outputs.dependencies).MACOS_X64_BOOT_JDK_URL }}" @@ -1380,7 +1402,7 @@ jobs: artifact: -debug env: - JDK_VERSION: "${{ fromJson(needs.prerequisites.outputs.dependencies).DEFAULT_VERSION_FEATURE }}" + JDK_VERSION: "${{ needs.prerequisites.outputs.jdk_version }}" BOOT_JDK_VERSION: "${{ fromJson(needs.prerequisites.outputs.dependencies).BOOT_JDK_VERSION }}" BOOT_JDK_FILENAME: "${{ fromJson(needs.prerequisites.outputs.dependencies).MACOS_X64_BOOT_JDK_FILENAME }}" BOOT_JDK_URL: "${{ fromJson(needs.prerequisites.outputs.dependencies).MACOS_X64_BOOT_JDK_URL }}" @@ -1510,7 +1532,7 @@ jobs: artifact: -debug env: - JDK_VERSION: "${{ fromJson(needs.prerequisites.outputs.dependencies).DEFAULT_VERSION_FEATURE }}" + JDK_VERSION: "${{ needs.prerequisites.outputs.jdk_version }}" BOOT_JDK_VERSION: "${{ fromJson(needs.prerequisites.outputs.dependencies).BOOT_JDK_VERSION }}" BOOT_JDK_FILENAME: "${{ fromJson(needs.prerequisites.outputs.dependencies).MACOS_X64_BOOT_JDK_FILENAME }}" BOOT_JDK_URL: "${{ fromJson(needs.prerequisites.outputs.dependencies).MACOS_X64_BOOT_JDK_URL }}" diff --git a/doc/building.html b/doc/building.html index 9cb1807345c905e42be6d1b7969d3b3b32e374d2..66e07f07b9d7dfd77115a01fb6dd5e490a634f70 100644 --- a/doc/building.html +++ b/doc/building.html @@ -163,6 +163,8 @@

Building on aarch64

At a minimum, a machine with 8 cores is advisable, as well as 8 GB of RAM. (The more cores to use, the more memory you need.) At least 6 GB of free disk space is required.

If you do not have access to sufficiently powerful hardware, it is also possible to use cross-compiling.

+

Branch Protection

+

In order to use Branch Protection features in the VM, --enable-branch-protection must be used. This option requires C++ compiler support (GCC 9.1.0+ or Clang 10+). The resulting build can be run on both machines with and without support for branch protection in hardware. Branch Protection is only supported for Linux targets.

Building on 32-bit arm

This is not recommended. Instead, see the section on Cross-compiling.

Operating System Requirements

@@ -214,7 +216,7 @@

Unfortunately, Cygwin can be unreliable in certain circumstances. If you experience build tool crashes or strange issues when building on Windows, please check the Cygwin FAQ on the "BLODA" list and the section on fork() failures.

Windows Subsystem for Linux (WSL)

Windows 10 1809 or newer is supported due to a dependency on the wslpath utility and support for environment variable sharing through WSLENV. Version 1803 can work but intermittent build failures have been observed.

-

It's possible to build both Windows and Linux binaries from WSL. To build Windows binaries, you must use a Windows boot JDK (located in a Windows-accessible directory). To build Linux binaries, you must use a Linux boot JDK. The default behavior is to build for Windows. To build for Linux, pass --build=x86_64-unknown-linux-gnu --host=x86_64-unknown-linux-gnu to configure.

+

It's possible to build both Windows and Linux binaries from WSL. To build Windows binaries, you must use a Windows boot JDK (located in a Windows-accessible directory). To build Linux binaries, you must use a Linux boot JDK. The default behavior is to build for Windows. To build for Linux, pass --build=x86_64-unknown-linux-gnu --openjdk-target=x86_64-unknown-linux-gnu to configure.

If building Windows binaries, the source code must be located in a Windows- accessible directory. This is because Windows executables (such as Visual Studio and the boot JDK) must be able to access the source code. Also, the drive where the source is stored must be mounted as case-insensitive by changing either /etc/fstab or /etc/wsl.conf in WSL. Individual directories may be corrected using the fsutil tool in case the source was cloned before changing the mount options.

Note that while it's possible to build on WSL, testing is still not fully supported.

macOS

@@ -271,7 +273,7 @@ Linux -gcc 10.2.0 +gcc 11.2.0 macOS @@ -286,7 +288,7 @@

All compilers are expected to be able to compile to the C99 language standard, as some C99 features are used in the source code. Microsoft Visual Studio doesn't fully support C99 so in practice shared code is limited to using C99 features that it does support.

gcc

The minimum accepted version of gcc is 5.0. Older versions will generate a warning by configure and are unlikely to work.

-

The JDK is currently known to be able to compile with at least version 10.2 of gcc.

+

The JDK is currently known to be able to compile with at least version 11.2 of gcc.

In general, any version between these two should be usable.

clang

The minimum accepted version of clang is 3.5. Older versions will not be accepted by configure.

@@ -568,7 +570,8 @@ x86_64-linux-gnu-to-ppc64le-linux-gnu

To be able to build, we need a "Build JDK", which is a JDK built from the current sources (that is, the same as the end result of the entire build process), but able to run on the build system, and not the target system. (In contrast, the Boot JDK should be from an older release, e.g. JDK 8 when building JDK 9.)

The build process will create a minimal Build JDK for you, as part of building. To speed up the build, you can use --with-build-jdk to configure to point to a pre-built Build JDK. Please note that the build result is unpredictable, and can possibly break in subtle ways, if the Build JDK does not exactly match the current sources.

Specifying the Target Platform

-

You must specify the target platform when cross-compiling. Doing so will also automatically turn the build into a cross-compiling mode. The simplest way to do this is to use the --openjdk-target argument, e.g. --openjdk-target=arm-linux-gnueabihf. or --openjdk-target=aarch64-oe-linux. This will automatically set the --build, --host and --target options for autoconf, which can otherwise be confusing. (In autoconf terminology, the "target" is known as "host", and "target" is used for building a Canadian cross-compiler.)

+

You must specify the target platform when cross-compiling. Doing so will also automatically turn the build into a cross-compiling mode. The simplest way to do this is to use the --openjdk-target argument, e.g. --openjdk-target=arm-linux-gnueabihf. or --openjdk-target=aarch64-oe-linux. This will automatically set the --host and --target options for autoconf, which can otherwise be confusing. (In autoconf terminology, the "target" is known as "host", and "target" is used for building a Canadian cross-compiler.)

+

If --build has not been explicitly passed to configure, --openjdk-target will autodetect the build platform and internally set the flag automatically, otherwise the platform that was explicitly passed to --build will be used instead.

Toolchain Considerations

You will need two copies of your toolchain, one which generates output that can run on the target system (the normal, or target, toolchain), and one that generates output that can run on the build system (the build toolchain). Note that cross-compiling is only supported for gcc at the time being. The gcc standard is to prefix cross-compiling toolchains with the target denominator. If you follow this standard, configure is likely to pick up the toolchain correctly.

The build toolchain will be autodetected just the same way the normal build/target toolchain will be autodetected when not cross-compiling. If this is not what you want, or if the autodetection fails, you can specify a devkit containing the build toolchain using --with-build-devkit to configure, or by giving BUILD_CC and BUILD_CXX arguments.

@@ -887,30 +890,28 @@ spawn failed

If you need general help or advice about developing for the JDK, you can also contact the Adoption Group. See the section on Contributing to OpenJDK for more information.

Reproducible Builds

Build reproducibility is the property of getting exactly the same bits out when building, every time, independent on who builds the product, or where. This is for many reasons a harder goal than it initially appears, but it is an important goal, for security reasons and others. Please see Reproducible Builds for more information about the background and reasons for reproducible builds.

-

Currently, it is not possible to build OpenJDK fully reproducibly, but getting there is an ongoing effort. There are some things you can do to minimize non-determinism and make a larger part of the build reproducible:

+

Currently, it is not possible to build OpenJDK fully reproducibly, but getting there is an ongoing effort.

+

An absolute prerequisite for building reproducible is to speficy a fixed build time, since time stamps are embedded in many file formats. This is done by setting the SOURCE_DATE_EPOCH environment variable, which is an industry standard, that many tools, such as gcc, recognize, and use in place of the current time when generating output.

+

To generate reproducible builds, you must set SOURCE_DATE_EPOCH before running configure. The value in SOURCE_DATE_EPOCH will be stored in the configuration, and used by make. Setting SOURCE_DATE_EPOCH before running make will have no effect on the build.

+

You must also make sure your build does not rely on configure's default adhoc version strings. Default adhoc version strings OPT segment include user name and source directory. You can either override just the OPT segment using --with-version-opt=<any fixed string>, or you can specify the entire version string using --with-version-string=<your version>.

+

This is a typical example of how to build the JDK in a reproducible way:

+
export SOURCE_DATE_EPOCH=946684800
+bash configure --with-version-opt=adhoc
+make
+

Note that regardless if you specify a source date for configure or not, the JDK build system will set SOURCE_DATE_EPOCH for all build tools when building. If --with-source-date has the value updated (which is the default unless SOURCE_DATE_EPOCH is found by in the environment by configure), the source date value will be determined at build time.

+

There are several aspects of reproducible builds that can be individually adjusted by configure arguments. If any of these are given, they will override the value derived from SOURCE_DATE_EPOCH. These arguments are:

-

Add the flag --enable-reproducible-build to your configure command line. This will turn on support for reproducible builds where it could otherwise be lacking.

- -

Default adhoc version strings OPT segment include user name, source directory and timestamp. You can either override just the OPT segment using --with-version-opt=<any fixed string>, or you can specify the entire version string using --with-version-string=<your version>.

- -

The JDK build system will set the SOURCE_DATE_EPOCH environment variable during building, depending on the value of the --with-source-date option for configure. The default value is updated, which means that SOURCE_DATE_EPOCH will be set to the current time each time you are running make.

-

The SOURCE_DATE_EPOCH environment variable is an industry standard, that many tools, such as gcc, recognize, and use in place of the current time when generating output.

-

For reproducible builds, you need to set this to a fixed value. You can use the special value version which will use the nominal release date for the current JDK version, or a value describing a date, either an epoch based timestamp as an integer, or a valid ISO-8601 date.

-

Hint: If your build environment already sets SOURCE_DATE_EPOCH, you can propagate this using --with-source-date=$SOURCE_DATE_EPOCH.

- -

Set a fixed hotspot build time. This will be included in the hotspot library (libjvm.so or jvm.dll) and defaults to the current time when building hotspot. Use --with-hotspot-build-time=<any fixed string> for reproducible builds. It's a string so you don't need to format it specifically, so e.g. n/a will do. Another solution is to use the SOURCE_DATE_EPOCH variable, e.g. --with-hotspot-build-time=$(date --date=@$SOURCE_DATE_EPOCH).

- -

The copyright year in some generated text files are normally set to the current year. This can be overridden by --with-copyright-year=<year>. For fully reproducible builds, this needs to be set to a fixed value.

Hints and Suggestions for Advanced Users

Bash Completion

The configure and make commands tries to play nice with bash command-line completion (using <tab> or <tab><tab>). To use this functionality, make sure you enable completion in your ~/.bashrc (see instructions for bash in your operating system).

diff --git a/doc/building.md b/doc/building.md index 459dbaa4c410109f14246746a217a8a33027284b..6bc5857811e763b10fe423b82f7cf9eb4c2b7868 100644 --- a/doc/building.md +++ b/doc/building.md @@ -135,6 +135,14 @@ space is required. If you do not have access to sufficiently powerful hardware, it is also possible to use [cross-compiling](#cross-compiling). +#### Branch Protection + +In order to use Branch Protection features in the VM, `--enable-branch-protection` +must be used. This option requires C++ compiler support (GCC 9.1.0+ or Clang +10+). The resulting build can be run on both machines with and without support +for branch protection in hardware. Branch Protection is only supported for +Linux targets. + ### Building on 32-bit arm This is not recommended. Instead, see the section on [Cross-compiling]( @@ -236,8 +244,8 @@ It's possible to build both Windows and Linux binaries from WSL. To build Windows binaries, you must use a Windows boot JDK (located in a Windows-accessible directory). To build Linux binaries, you must use a Linux boot JDK. The default behavior is to build for Windows. To build for Linux, pass -`--build=x86_64-unknown-linux-gnu --host=x86_64-unknown-linux-gnu` to -`configure`. +`--build=x86_64-unknown-linux-gnu --openjdk-target=x86_64-unknown-linux-gnu` +to `configure`. If building Windows binaries, the source code must be located in a Windows- accessible directory. This is because Windows executables (such as Visual Studio @@ -321,7 +329,7 @@ issues. Operating system Toolchain version ------------------ ------------------------------------------------------- - Linux gcc 10.2.0 + Linux gcc 11.2.0 macOS Apple Xcode 10.1 (using clang 10.0.0) Windows Microsoft Visual Studio 2019 update 16.7.2 @@ -335,7 +343,7 @@ features that it does support. The minimum accepted version of gcc is 5.0. Older versions will generate a warning by `configure` and are unlikely to work. -The JDK is currently known to be able to compile with at least version 10.2 of +The JDK is currently known to be able to compile with at least version 11.2 of gcc. In general, any version between these two should be usable. @@ -374,9 +382,9 @@ available for this update. ### Microsoft Visual Studio -For aarch64 machines running Windows the minimum accepted version is Visual Studio 2019 -(16.8 or higher). For all other platforms the minimum accepted version of -Visual Studio is 2017. Older versions will not be accepted by `configure` and will +For aarch64 machines running Windows the minimum accepted version is Visual Studio 2019 +(16.8 or higher). For all other platforms the minimum accepted version of +Visual Studio is 2017. Older versions will not be accepted by `configure` and will not work. For all platforms the maximum accepted version of Visual Studio is 2022. If you have multiple versions of Visual Studio installed, `configure` will by @@ -978,11 +986,16 @@ You *must* specify the target platform when cross-compiling. Doing so will also automatically turn the build into a cross-compiling mode. The simplest way to do this is to use the `--openjdk-target` argument, e.g. `--openjdk-target=arm-linux-gnueabihf`. or `--openjdk-target=aarch64-oe-linux`. -This will automatically set the `--build`, `--host` and `--target` options for +This will automatically set the `--host` and `--target` options for autoconf, which can otherwise be confusing. (In autoconf terminology, the "target" is known as "host", and "target" is used for building a Canadian cross-compiler.) +If `--build` has not been explicitly passed to configure, `--openjdk-target` +will autodetect the build platform and internally set the flag automatically, +otherwise the platform that was explicitly passed to `--build` will be used +instead. + ### Toolchain Considerations You will need two copies of your toolchain, one which generates output that can @@ -1514,57 +1527,85 @@ https://reproducible-builds.org) for more information about the background and reasons for reproducible builds. Currently, it is not possible to build OpenJDK fully reproducibly, but getting -there is an ongoing effort. There are some things you can do to minimize -non-determinism and make a larger part of the build reproducible: +there is an ongoing effort. + +An absolute prerequisite for building reproducible is to speficy a fixed build +time, since time stamps are embedded in many file formats. This is done by +setting the `SOURCE_DATE_EPOCH` environment variable, which is an [industry +standard]( https://reproducible-builds.org/docs/source-date-epoch/), that many +tools, such as gcc, recognize, and use in place of the current time when +generating output. + +To generate reproducible builds, you must set `SOURCE_DATE_EPOCH` before running +`configure`. The value in `SOURCE_DATE_EPOCH` will be stored in the +configuration, and used by `make`. Setting `SOURCE_DATE_EPOCH` before running +`make` will have no effect on the build. + +You must also make sure your build does not rely on `configure`'s default adhoc +version strings. Default adhoc version strings `OPT` segment include user name +and source directory. You can either override just the `OPT` segment using +`--with-version-opt=`, or you can specify the entire version +string using `--with-version-string=`. - * Turn on build system support for reproducible builds +This is a typical example of how to build the JDK in a reproducible way: -Add the flag `--enable-reproducible-build` to your `configure` command line. -This will turn on support for reproducible builds where it could otherwise be -lacking. +``` +export SOURCE_DATE_EPOCH=946684800 +bash configure --with-version-opt=adhoc +make +``` - * Do not rely on `configure`'s default adhoc version strings +Note that regardless if you specify a source date for `configure` or not, the +JDK build system will set `SOURCE_DATE_EPOCH` for all build tools when building. +If `--with-source-date` has the value `updated` (which is the default unless +`SOURCE_DATE_EPOCH` is found by in the environment by `configure`), the source +date value will be determined at build time. -Default adhoc version strings OPT segment include user name, source directory -and timestamp. You can either override just the OPT segment using -`--with-version-opt=`, or you can specify the entire version -string using `--with-version-string=`. +There are several aspects of reproducible builds that can be individually +adjusted by `configure` arguments. If any of these are given, they will override +the value derived from `SOURCE_DATE_EPOCH`. These arguments are: - * Specify how the build sets `SOURCE_DATE_EPOCH` + * `--with-source-date` -The JDK build system will set the `SOURCE_DATE_EPOCH` environment variable -during building, depending on the value of the `--with-source-date` option for -`configure`. The default value is `updated`, which means that -`SOURCE_DATE_EPOCH` will be set to the current time each time you are running -`make`. + This option controls how the JDK build sets `SOURCE_DATE_EPOCH` when + building. It can be set to a value describing a date, either an epoch based + timestamp as an integer, or a valid ISO-8601 date. -The [`SOURCE_DATE_EPOCH` environment variable]( -https://reproducible-builds.org/docs/source-date-epoch/) is an industry -standard, that many tools, such as gcc, recognize, and use in place of the -current time when generating output. + It can also be set to one of the special values `current`, `updated` or + `version`. `current` means that the time of running `configure` will be + used. `version` will use the nominal release date for the current JDK + version. `updated`, which means that `SOURCE_DATE_EPOCH` will be set to the + current time each time you are running `make`. All choices, except for + `updated`, will set a fixed value for the source date timestamp. -For reproducible builds, you need to set this to a fixed value. You can use the -special value `version` which will use the nominal release date for the current -JDK version, or a value describing a date, either an epoch based timestamp as an -integer, or a valid ISO-8601 date. + When `SOURCE_DATE_EPOCH` is set, the default value for `--with-source-date` + will be the value given by `SOURCE_DATE_EPOCH`. Otherwise, the default value + is `updated`. -**Hint:** If your build environment already sets `SOURCE_DATE_EPOCH`, you can -propagate this using `--with-source-date=$SOURCE_DATE_EPOCH`. + * `--with-hotspot-build-time` + + This option controls the build time string that will be included in the + hotspot library (`libjvm.so` or `jvm.dll`). When the source date is fixed + (e.g. by setting `SOURCE_DATE_EPOCH`), the default value for + `--with-hotspot-build-time` will be an ISO 8601 representation of that time + stamp. Otherwise the default value will be the current time when building + hotspot. - * Specify a hotspot build time + * `--with-copyright-year` -Set a fixed hotspot build time. This will be included in the hotspot library -(`libjvm.so` or `jvm.dll`) and defaults to the current time when building -hotspot. Use `--with-hotspot-build-time=` for reproducible -builds. It's a string so you don't need to format it specifically, so e.g. `n/a` -will do. Another solution is to use the `SOURCE_DATE_EPOCH` variable, e.g. -`--with-hotspot-build-time=$(date --date=@$SOURCE_DATE_EPOCH)`. + This option controls the copyright year in some generated text files. When + the source date is fixed (e.g. by setting `SOURCE_DATE_EPOCH`), the default + value for `--with-copyright-year` will be the year of that time stamp. + Otherwise the default is the current year at the time of running configure. + This can be overridden by `--with-copyright-year=`. - * Copyright year + * `--enable-reproducible-build` -The copyright year in some generated text files are normally set to the current -year. This can be overridden by `--with-copyright-year=`. For fully -reproducible builds, this needs to be set to a fixed value. + This option controls some additional behavior needed to make the build + reproducible. When the source date is fixed (e.g. by setting + `SOURCE_DATE_EPOCH`), this flag will be turned on by default. Otherwise, the + value is determined by heuristics. If it is explicitly turned off, the build + might not be reproducible. ## Hints and Suggestions for Advanced Users diff --git a/doc/hotspot-style.html b/doc/hotspot-style.html index eb0c8de2ae54bd218b5fd8ef2b7d12cd241cdcf6..c93b941c9885fbfc640175f2cfeb82f711cce3cc 100644 --- a/doc/hotspot-style.html +++ b/doc/hotspot-style.html @@ -68,7 +68,7 @@

Many of the guidelines mentioned here have (sometimes widespread) counterexamples in the HotSpot code base. Finding a counterexample is not sufficient justification for new code to follow the counterexample as a precedent, since readers of your code will rightfully expect your code to follow the greater bulk of precedents documented here.

Occasionally a guideline mentioned here may be just out of synch with the actual HotSpot code base. If you find that a guideline is consistently contradicted by a large number of counterexamples, please bring it up for discussion and possible change. The architectural rule, of course, is "When in Rome do as the Romans". Sometimes in the suburbs of Rome the rules are a little different; these differences can be pointed out here.

Proposed changes should be discussed on the HotSpot Developers mailing list. Changes are likely to be cautious and incremental, since HotSpot coders have been using these guidelines for years.

-

Substantive changes are approved by rough consensus of the HotSpot Group Members. The Group Lead determines whether consensus has been reached.

+

Substantive changes are approved by rough consensus of the HotSpot Group Members. The Group Lead determines whether consensus has been reached.

Editorial changes (changes that only affect the description of HotSpot style, not its substance) do not require the full consensus gathering process. The normal HotSpot pull request process may be used for editorial changes, with the additional requirement that the requisite reviewers are also HotSpot Group Members.

Structure and Formatting

Factoring and Class Design

@@ -153,7 +153,7 @@

Whitespace

  • In general, don't change whitespace unless it improves readability or consistency. Gratuitous whitespace changes will make integrations and backports more difficult.

  • -
  • Use One-True-Brace-Style. The opening brace for a function or class is normally at the end of the line; it is sometimes moved to the beginning of the next line for emphasis. Substatements are enclosed in braces, even if there is only a single statement. Extremely simple one-line statements may drop braces around a substatement.

  • +
  • Use One-True-Brace-Style. The opening brace for a function or class is normally at the end of the line; it is sometimes moved to the beginning of the next line for emphasis. Substatements are enclosed in braces, even if there is only a single statement. Extremely simple one-line statements may drop braces around a substatement.

  • Indentation levels are two columns.

  • There is no hard line length limit. That said, bear in mind that excessively long lines can cause difficulties. Some people like to have multiple side-by-side windows in their editors, and long lines may force them to choose among unpleasant options. They can use wide windows, reducing the number that can fit across the screen, and wasting a lot of screen real estate because most lines are not that long. Alternatively, they can have more windows across the screen, with long lines wrapping (or worse, requiring scrolling to see in their entirety), which is harder to read. Similar issues exist for side-by-side code reviews.

  • Tabs are not allowed in code. Set your editor accordingly.
    (Emacs: (setq-default indent-tabs-mode nil).)

  • @@ -210,7 +210,7 @@ while ( test_foo(args...) ) { // No, excess spaces around controlRationale: Other than to implement exceptions (which HotSpot doesn't use), most potential uses of RTTI are better done via virtual functions. Some of the remainder can be replaced by bespoke mechanisms. The cost of the additional runtime data structures needed to support RTTI are deemed not worthwhile, given the alternatives.

    Memory Allocation

    Do not use the standard global allocation and deallocation functions (operator new and related functions). Use of these functions by HotSpot code is disabled for some platforms.

    -

    Rationale: HotSpot often uses "resource" or "arena" allocation. Even where heap allocation is used, the standard global functions are avoided in favor of wrappers around malloc and free that support the VM's Native Memory Tracking (NMT) feature.

    +

    Rationale: HotSpot often uses "resource" or "arena" allocation. Even where heap allocation is used, the standard global functions are avoided in favor of wrappers around malloc and free that support the VM's Native Memory Tracking (NMT) feature. Typically, uses of the global operator new are inadvertent and therefore often associated with memory leaks.

    Native memory allocation failures are often treated as non-recoverable. The place where "out of memory" is (first) detected may be an innocent bystander, unrelated to the actual culprit.

    Class Inheritance

    Use public single inheritance.

    @@ -270,8 +270,8 @@ while ( test_foo(args...) ) { // No, excess spaces around controlThe underlying type of a scoped-enum should also be specified explicitly if conversions may be applied to values of that type.

    Due to bugs in certain (very old) compilers, there is widespread use of enums and avoidance of in-class initialization of static integral constant members. Compilers having such bugs are no longer supported. Except where an enum is semantically appropriate, new code should use integral constants.

    thread_local

    -

    Do not use thread_local (n2659); instead, use the HotSpot macro THREAD_LOCAL. The initializer must be a constant expression.

    -

    As was discussed in the review for JDK-8230877, thread_local allows dynamic initialization and destruction semantics. However, that support requires a run-time penalty for references to non-function-local thread_local variables defined in a different translation unit, even if they don't need dynamic initialization. Dynamic initialization and destruction of namespace-scoped thread local variables also has the same ordering problems as for ordinary namespace-scoped variables.

    +

    Avoid use of thread_local (n2659); and instead, use the HotSpot macro THREAD_LOCAL, for which the initializer must be a constant expression. When thread_local must be used, use the Hotspot macro APPROVED_CPP_THREAD_LOCAL to indicate that the use has been given appropriate consideration.

    +

    As was discussed in the review for JDK-8230877, thread_local allows dynamic initialization and destruction semantics. However, that support requires a run-time penalty for references to non-function-local thread_local variables defined in a different translation unit, even if they don't need dynamic initialization. Dynamic initialization and destruction of non-local thread_local variables also has the same ordering problems as for ordinary non-local variables. So we avoid use of thread_local in general, limiting its use to only those cases where dynamic initialization or destruction are essential. See JDK-8282469 for further discussion.

    nullptr

    Prefer nullptr (n2431) to NULL. Don't use (constexpr or literal) 0 for pointers.

    For historical reasons there are widespread uses of both NULL and of integer 0 as a pointer value.

    @@ -438,7 +438,7 @@ while ( test_foo(args...) ) { // No, excess spaces around control

    Inline namespaces (n2535) — HotSpot makes very limited use of namespaces.

  • using namespace directives. In particular, don't use using namespace std; to avoid needing to qualify Standard Library names.

  • Propagating exceptions (n2179) — HotSpot does not permit the use of exceptions, so this feature isn't useful.

  • -
  • Avoid namespace-scoped variables with non-constexpr initialization. In particular, avoid variables with types requiring non-trivial initialization or destruction. Initialization order problems can be difficult to deal with and lead to surprises, as can destruction ordering. HotSpot doesn't generally try to cleanup on exit, and running destructors at exit can also lead to problems.

  • +
  • Avoid non-local variables with non-constexpr initialization. In particular, avoid variables with types requiring non-trivial initialization or destruction. Initialization order problems can be difficult to deal with and lead to surprises, as can destruction ordering. HotSpot doesn't generally try to cleanup on exit, and running destructors at exit can also lead to problems.

  • [[deprecated]] attribute (n3760) — Not relevant in HotSpot code.

  • Avoid most operator overloading, preferring named functions. When operator overloading is used, ensure the semantics conform to the normal expected behavior of the operation.

  • Avoid most implicit conversion constructors and (implicit or explicit) conversion operators. (Note that conversion to bool isn't needed in HotSpot code because of the "no implicit boolean" guideline.)

  • diff --git a/doc/hotspot-style.md b/doc/hotspot-style.md index 4efce0301b275b467527473d17a8e72d1ce1f551..89d9684672db0ea1960f789e3aa39bc40ccb4bee 100644 --- a/doc/hotspot-style.md +++ b/doc/hotspot-style.md @@ -60,7 +60,7 @@ list. Changes are likely to be cautious and incremental, since HotSpot coders have been using these guidelines for years. Substantive changes are approved by -[rough consensus](https://en.wikipedia.org/wiki/Rough_consensus) of +[rough consensus](https://www.rfc-editor.org/rfc/rfc7282.html) of the [HotSpot Group](https://openjdk.java.net/census#hotspot) Members. The Group Lead determines whether consensus has been reached. @@ -294,7 +294,9 @@ well. or consistency. Gratuitous whitespace changes will make integrations and backports more difficult. -* Use One-True-Brace-Style. The opening brace for a function or class +* Use [One-True-Brace-Style]( +https://en.wikipedia.org/wiki/Indentation_style#Variant:_1TBS_(OTBS)). +The opening brace for a function or class is normally at the end of the line; it is sometimes moved to the beginning of the next line for emphasis. Substatements are enclosed in braces, even if there is only a single statement. Extremely simple @@ -469,7 +471,9 @@ code is disabled for some platforms. Rationale: HotSpot often uses "resource" or "arena" allocation. Even where heap allocation is used, the standard global functions are avoided in favor of wrappers around malloc and free that support the -VM's Native Memory Tracking (NMT) feature. +VM's Native Memory Tracking (NMT) feature. Typically, uses of the global +operator new are inadvertent and therefore often associated with memory +leaks. Native memory allocation failures are often treated as non-recoverable. The place where "out of memory" is (first) detected may be an innocent @@ -629,7 +633,7 @@ Here are a few closely related example bugs:
    ### enum Where appropriate, _scoped-enums_ should be used. -([n2347](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2347.pdf)) +([n2347](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2347.pdf)) Use of _unscoped-enums_ is permitted, though ordinary constants may be preferable when the automatic initializer feature isn't used. @@ -649,10 +653,12 @@ integral constants. ### thread_local -Do not use `thread_local` +Avoid use of `thread_local` ([n2659](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2659.htm)); -instead, use the HotSpot macro `THREAD_LOCAL`. The initializer must -be a constant expression. +and instead, use the HotSpot macro `THREAD_LOCAL`, for which the initializer must +be a constant expression. When `thread_local` must be used, use the Hotspot macro +`APPROVED_CPP_THREAD_LOCAL` to indicate that the use has been given appropriate +consideration. As was discussed in the review for [JDK-8230877](https://mail.openjdk.java.net/pipermail/hotspot-dev/2019-September/039487.html), @@ -661,14 +667,18 @@ semantics. However, that support requires a run-time penalty for references to non-function-local `thread_local` variables defined in a different translation unit, even if they don't need dynamic initialization. Dynamic initialization and destruction of -namespace-scoped thread local variables also has the same ordering -problems as for ordinary namespace-scoped variables. +non-local `thread_local` variables also has the same ordering +problems as for ordinary non-local variables. So we avoid use of +`thread_local` in general, limiting its use to only those cases where dynamic +initialization or destruction are essential. See +[JDK-8282469](https://bugs.openjdk.java.net/browse/JDK-8282469) +for further discussion. ### nullptr Prefer `nullptr` ([n2431](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2431.pdf)) -to `NULL`. Don't use (constexpr or literal) 0 for pointers. +to `NULL`. Don't use (constexpr or literal) 0 for pointers. For historical reasons there are widespread uses of both `NULL` and of integer 0 as a pointer value. @@ -937,7 +947,7 @@ References: * Generalized lambda capture (init-capture) ([N3648]) * Generic (polymorphic) lambda expressions ([N3649]) -[n2657]: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2657.htm +[n2657]: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2657.htm [n2927]: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2009/n2927.pdf [N3648]: https://isocpp.org/files/papers/N3648.html [N3649]: https://isocpp.org/files/papers/N3649.html @@ -978,7 +988,7 @@ References from C++23 ### Additional Permitted Features * `constexpr` -([n2235](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2235.pdf)) +([n2235](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2235.pdf)) ([n3652](https://isocpp.org/files/papers/N3652.html)) * Sized deallocation @@ -1064,7 +1074,7 @@ namespace std;` to avoid needing to qualify Standard Library names. ([n2179](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2179.html)) — HotSpot does not permit the use of exceptions, so this feature isn't useful. -* Avoid namespace-scoped variables with non-constexpr initialization. +* Avoid non-local variables with non-constexpr initialization. In particular, avoid variables with types requiring non-trivial initialization or destruction. Initialization order problems can be difficult to deal with and lead to surprises, as can destruction @@ -1085,14 +1095,14 @@ in HotSpot code because of the "no implicit boolean" guideline.) * Avoid covariant return types. -* Avoid `goto` statements. +* Avoid `goto` statements. ### Undecided Features This list is incomplete; it serves to explicitly call out some features that have not yet been discussed. -* Trailing return type syntax for functions +* Trailing return type syntax for functions ([n2541](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2541.htm)) * Variable templates @@ -1106,7 +1116,7 @@ features that have not yet been discussed. * Rvalue references and move semantics -[ADL]: https://en.cppreference.com/w/cpp/language/adl +[ADL]: https://en.cppreference.com/w/cpp/language/adl "Argument Dependent Lookup" [ODR]: https://en.cppreference.com/w/cpp/language/definition diff --git a/make/Hsdis.gmk b/make/Hsdis.gmk index 02f09b320f095522d29e0e7d7e73438a10f2ee72..ec06a89aaab1f3c714a9213cefc9790b4d07fdd1 100644 --- a/make/Hsdis.gmk +++ b/make/Hsdis.gmk @@ -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 @@ -35,107 +35,165 @@ include JdkNativeCompilation.gmk ################################################################################ HSDIS_OUTPUT_DIR := $(SUPPORT_OUTPUTDIR)/hsdis +REAL_HSDIS_NAME := hsdis-$(OPENJDK_TARGET_CPU_LEGACY_LIB)$(SHARED_LIBRARY_SUFFIX) +BUILT_HSDIS_LIB := $(HSDIS_OUTPUT_DIR)/$(REAL_HSDIS_NAME) + +HSDIS_TOOLCHAIN := TOOLCHAIN_DEFAULT +HSDIS_TOOLCHAIN_CFLAGS := $(CFLAGS_JDKLIB) +HSDIS_TOOLCHAIN_LDFLAGS := $(LDFLAGS_JDKLIB) + +ifeq ($(HSDIS_BACKEND), capstone) + ifeq ($(call isTargetCpuArch, x86), true) + CAPSTONE_ARCH := CS_ARCH_X86 + CAPSTONE_MODE := CS_MODE_$(OPENJDK_TARGET_CPU_BITS) + else ifeq ($(call isTargetCpuArch, aarch64), true) + CAPSTONE_ARCH := CS_ARCH_ARM64 + CAPSTONE_MODE := CS_MODE_ARM + else + $(error No support for Capstone on this platform) + endif -ifeq ($(call isTargetOs, windows), true) - INSTALLED_HSDIS_DIR := $(JDK_OUTPUTDIR)/bin + HSDIS_CFLAGS += -DCAPSTONE_ARCH=$(CAPSTONE_ARCH) \ + -DCAPSTONE_MODE=$(CAPSTONE_MODE) +endif - # On windows, we need to "fake" a completely different toolchain using gcc - # instead of the normal microsoft toolchain. This is quite hacky... +ifeq ($(HSDIS_BACKEND), llvm) + # Use C++ instead of C + HSDIS_TOOLCHAIN_CFLAGS := $(CXXFLAGS_JDKLIB) + HSDIS_TOOLCHAIN := TOOLCHAIN_LINK_CXX + + ifeq ($(call isTargetOs, linux), true) + LLVM_OS := pc-linux-gnu + else ifeq ($(call isTargetOs, macosx), true) + LLVM_OS := apple-darwin + else ifeq ($(call isTargetOs, windows), true) + LLVM_OS := pc-windows-msvc + else + $(error No support for LLVM on this platform) + endif - MINGW_BASE := x86_64-w64-mingw32 + HSDIS_CFLAGS += -DLLVM_DEFAULT_TRIPLET='"$(OPENJDK_TARGET_CPU)-$(LLVM_OS)"' +endif - MINGW_SYSROOT = $(shell $(MINGW_BASE)-gcc -print-sysroot) - ifeq ($(wildcard $(MINGW_SYSROOT)), ) - # Use fallback path - MINGW_SYSROOT := /usr/$(MINGW_BASE) +ifeq ($(HSDIS_BACKEND), binutils) + ifeq ($(call isTargetOs, windows), true) + # On windows, we need to "fake" a completely different toolchain using gcc + # instead of the normal microsoft toolchain. This is quite hacky... + + MINGW_BASE := x86_64-w64-mingw32 + + MINGW_SYSROOT = $(shell $(MINGW_BASE)-gcc -print-sysroot) ifeq ($(wildcard $(MINGW_SYSROOT)), ) - $(error mingw sysroot not found) + # Use fallback path + MINGW_SYSROOT := /usr/$(MINGW_BASE) + ifeq ($(wildcard $(MINGW_SYSROOT)), ) + $(error mingw sysroot not found) + endif endif - endif - $(eval $(call DefineNativeToolchain, TOOLCHAIN_MINGW, \ - CC := $(MINGW_BASE)-gcc, \ - LD := $(MINGW_BASE)-ld, \ - OBJCOPY := $(MINGW_BASE)-objcopy, \ - RC := $(RC), \ - SYSROOT_CFLAGS := --sysroot=$(MINGW_SYSROOT), \ - SYSROOT_LDFLAGS := --sysroot=$(MINGW_SYSROOT), \ - )) - - MINGW_SYSROOT_LIB_PATH := $(MINGW_SYSROOT)/mingw/lib - ifeq ($(wildcard $(MINGW_SYSROOT_LIB_PATH)), ) - # Try without mingw - MINGW_SYSROOT_LIB_PATH := $(MINGW_SYSROOT)/lib + $(eval $(call DefineNativeToolchain, TOOLCHAIN_MINGW, \ + CC := $(MINGW_BASE)-gcc, \ + LD := $(MINGW_BASE)-ld, \ + OBJCOPY := $(MINGW_BASE)-objcopy, \ + RC := $(RC), \ + SYSROOT_CFLAGS := --sysroot=$(MINGW_SYSROOT), \ + SYSROOT_LDFLAGS := --sysroot=$(MINGW_SYSROOT), \ + )) + + MINGW_SYSROOT_LIB_PATH := $(MINGW_SYSROOT)/mingw/lib ifeq ($(wildcard $(MINGW_SYSROOT_LIB_PATH)), ) - $(error mingw sysroot lib path not found) + # Try without mingw + MINGW_SYSROOT_LIB_PATH := $(MINGW_SYSROOT)/lib + ifeq ($(wildcard $(MINGW_SYSROOT_LIB_PATH)), ) + $(error mingw sysroot lib path not found) + endif endif - endif - MINGW_VERSION = $(shell $(MINGW_BASE)-gcc -v 2>&1 | $(GREP) "gcc version" | $(CUT) -d " " -f 3) - MINGW_GCC_LIB_PATH := /usr/lib/gcc/$(MINGW_BASE)/$(MINGW_VERSION) - ifeq ($(wildcard $(MINGW_GCC_LIB_PATH)), ) - # Try using only major version number - MINGW_VERSION_MAJOR := $(firstword $(subst ., , $(MINGW_VERSION))) - MINGW_GCC_LIB_PATH := /usr/lib/gcc/$(MINGW_BASE)/$(MINGW_VERSION_MAJOR) + MINGW_VERSION = $(shell $(MINGW_BASE)-gcc -v 2>&1 | $(GREP) "gcc version" | $(CUT) -d " " -f 3) + MINGW_GCC_LIB_PATH := /usr/lib/gcc/$(MINGW_BASE)/$(MINGW_VERSION) ifeq ($(wildcard $(MINGW_GCC_LIB_PATH)), ) - $(error mingw gcc lib path not found) + # Try using only major version number + MINGW_VERSION_MAJOR := $(firstword $(subst ., , $(MINGW_VERSION))) + MINGW_GCC_LIB_PATH := /usr/lib/gcc/$(MINGW_BASE)/$(MINGW_VERSION_MAJOR) + ifeq ($(wildcard $(MINGW_GCC_LIB_PATH)), ) + $(error mingw gcc lib path not found) + endif endif - endif - TOOLCHAIN_TYPE := gcc - OPENJDK_TARGET_OS := linux - CC_OUT_OPTION := -o$(SPACE) - LD_OUT_OPTION := -o$(SPACE) - GENDEPS_FLAGS := -MMD -MF - CFLAGS_DEBUG_SYMBOLS := -g - DISABLED_WARNINGS := - DISABLE_WARNING_PREFIX := -Wno- - CFLAGS_WARNINGS_ARE_ERRORS := -Werror - SHARED_LIBRARY_FLAGS := -shared - - HSDIS_TOOLCHAIN := TOOLCHAIN_MINGW - HSDIS_TOOLCHAIN_CFLAGS := - HSDIS_TOOLCHAIN_LDFLAGS := -L$(MINGW_GCC_LIB_PATH) -L$(MINGW_SYSROOT_LIB_PATH) - MINGW_DLLCRT := $(MINGW_SYSROOT_LIB_PATH)/dllcrt2.o - HSDIS_TOOLCHAIN_LIBS := $(MINGW_DLLCRT) -lmingw32 -lgcc -lgcc_eh -lmoldname \ - -lmingwex -lmsvcrt -lpthread -ladvapi32 -lshell32 -luser32 -lkernel32 -else - INSTALLED_HSDIS_DIR := $(JDK_OUTPUTDIR)/lib - - HSDIS_TOOLCHAIN := TOOLCHAIN_DEFAULT - HSDIS_TOOLCHAIN_CFLAGS := $(CFLAGS_JDKLIB) - HSDIS_TOOLCHAIN_LDFLAGS := $(LDFLAGS_JDKLIB) - HSDIS_TOOLCHAIN_LIBS := -ldl + TOOLCHAIN_TYPE := gcc + OPENJDK_TARGET_OS := linux + CC_OUT_OPTION := -o$(SPACE) + LD_OUT_OPTION := -o$(SPACE) + GENDEPS_FLAGS := -MMD -MF + CFLAGS_DEBUG_SYMBOLS := -g + DISABLED_WARNINGS := + DISABLE_WARNING_PREFIX := -Wno- + CFLAGS_WARNINGS_ARE_ERRORS := -Werror + SHARED_LIBRARY_FLAGS := -shared + + HSDIS_TOOLCHAIN := TOOLCHAIN_MINGW + HSDIS_TOOLCHAIN_CFLAGS := + HSDIS_TOOLCHAIN_LDFLAGS := -L$(MINGW_GCC_LIB_PATH) -L$(MINGW_SYSROOT_LIB_PATH) + MINGW_DLLCRT := $(MINGW_SYSROOT_LIB_PATH)/dllcrt2.o + HSDIS_TOOLCHAIN_LIBS := $(MINGW_DLLCRT) -lmingw32 -lgcc -lgcc_eh -lmoldname \ + -lmingwex -lmsvcrt -lpthread -ladvapi32 -lshell32 -luser32 -lkernel32 + else + HSDIS_TOOLCHAIN_LIBS := -ldl + endif endif - $(eval $(call SetupJdkLibrary, BUILD_HSDIS, \ NAME := hsdis, \ - SRC := $(TOPDIR)/src/utils/hsdis, \ + SRC := $(TOPDIR)/src/utils/hsdis/$(HSDIS_BACKEND), \ + EXTRA_HEADER_DIRS := $(TOPDIR)/src/utils/hsdis, \ TOOLCHAIN := $(HSDIS_TOOLCHAIN), \ OUTPUT_DIR := $(HSDIS_OUTPUT_DIR), \ OBJECT_DIR := $(HSDIS_OUTPUT_DIR), \ DISABLED_WARNINGS_gcc := undef format-nonliteral sign-compare, \ DISABLED_WARNINGS_clang := undef format-nonliteral, \ CFLAGS := $(HSDIS_TOOLCHAIN_CFLAGS) $(HSDIS_CFLAGS), \ - LDFLAGS := $(HSDIS_TOOLCHAIN_LDFLAGS) $(SHARED_LIBRARY_FLAGS), \ + LDFLAGS := $(HSDIS_TOOLCHAIN_LDFLAGS) $(HSDIS_LDFLAGS) $(SHARED_LIBRARY_FLAGS), \ LIBS := $(HSDIS_LIBS) $(HSDIS_TOOLCHAIN_LIBS), \ )) -build: $(BUILD_HSDIS) +$(BUILT_HSDIS_LIB): $(BUILD_HSDIS_TARGET) + $(install-file) + +build: $(BUILD_HSDIS) $(BUILT_HSDIS_LIB) TARGETS += build -INSTALLED_HSDIS_NAME := hsdis-$(OPENJDK_TARGET_CPU_LEGACY_LIB)$(SHARED_LIBRARY_SUFFIX) +ifeq ($(ENABLE_HSDIS_BUNDLING), false) + + ifeq ($(call isTargetOs, windows), true) + JDK_HSDIS_DIR := $(JDK_OUTPUTDIR)/bin + IMAGE_HSDIS_DIR := $(JDK_IMAGE_DIR)/bin + else + JDK_HSDIS_DIR := $(JDK_OUTPUTDIR)/lib + IMAGE_HSDIS_DIR := $(JDK_IMAGE_DIR)/lib + endif + -INSTALLED_HSDIS := $(INSTALLED_HSDIS_DIR)/$(INSTALLED_HSDIS_NAME) + INSTALLED_HSDIS_JDK := $(JDK_HSDIS_DIR)/$(REAL_HSDIS_NAME) + INSTALLED_HSDIS_IMAGE := $(IMAGE_HSDIS_DIR)/$(REAL_HSDIS_NAME) -$(INSTALLED_HSDIS): $(BUILD_HSDIS_TARGET) - $(call LogWarn, NOTE: The resulting build might not be redistributable. Seek legal advice before distibuting.) + $(INSTALLED_HSDIS_JDK): $(BUILT_HSDIS_LIB) + ifeq ($(HSDIS_BACKEND), binutils) + $(call LogWarn, NOTE: The resulting build might not be redistributable. Seek legal advice before distributing.) + endif $(install-file) + $(INSTALLED_HSDIS_IMAGE): $(BUILT_HSDIS_LIB) + $(install-file) + + install: $(INSTALLED_HSDIS_JDK) $(INSTALLED_HSDIS_IMAGE) + +else + + install: + $(ECHO) NOTE: make install-hsdis is a no-op with --enable-hsdis-bundling -install: $(INSTALLED_HSDIS) +endif TARGETS += install diff --git a/make/InitSupport.gmk b/make/InitSupport.gmk index d2291c50f2161c41ebd5681cecebc4c9b2a11471..62fdc438c8a68e2e6c09717ab8d7472368bdb2e0 100644 --- a/make/InitSupport.gmk +++ b/make/InitSupport.gmk @@ -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 @@ -310,17 +310,16 @@ else # $(HAS_SPEC)=true # level of reproducible builds define SetupReproducibleBuild ifeq ($$(SOURCE_DATE), updated) - SOURCE_DATE := $$(shell $$(DATE) +"%s") - endif - export SOURCE_DATE_EPOCH := $$(SOURCE_DATE) - ifeq ($$(IS_GNU_DATE), yes) - export SOURCE_DATE_ISO_8601 := $$(shell $$(DATE) --utc \ - --date="@$$(SOURCE_DATE_EPOCH)" \ - +"%Y-%m-%dT%H:%M:%SZ" 2> /dev/null) - else - export SOURCE_DATE_ISO_8601 := $$(shell $$(DATE) -u \ - -j -f "%s" "$$(SOURCE_DATE_EPOCH)" \ - +"%Y-%m-%dT%H:%M:%SZ" 2> /dev/null) + # For static values of SOURCE_DATE (not "updated"), these are set in spec.gmk + export SOURCE_DATE_EPOCH := $$(shell $$(DATE) +"%s") + ifeq ($$(IS_GNU_DATE), yes) + export SOURCE_DATE_ISO_8601 := $$(shell $$(DATE) --utc \ + --date="@$$(SOURCE_DATE_EPOCH)" +"$$(ISO_8601_FORMAT_STRING)" \ + 2> /dev/null) + else + export SOURCE_DATE_ISO_8601 := $$(shell $$(DATE) -u -j -f "%s" \ + "$$(SOURCE_DATE_EPOCH)" +"$$(ISO_8601_FORMAT_STRING)" 2> /dev/null) + endif endif endef diff --git a/make/Main.gmk b/make/Main.gmk index e5ea250bf5aad0dc77180792072e3e5bf2cce7f1..26e470f9c40a2e8bbb620e0cf963fa73bd196f13 100644 --- a/make/Main.gmk +++ b/make/Main.gmk @@ -535,6 +535,7 @@ ifneq ($(HSDIS_BACKEND), none) $(eval $(call SetupTarget, install-hsdis, \ MAKEFILE := Hsdis, \ TARGET := install, \ + DEPS := jdk-image, \ )) endif @@ -861,6 +862,10 @@ else $(foreach t, $(filter-out java.base-libs, $(LIBS_TARGETS)), \ $(eval $t: java.base-libs)) + ifeq ($(ENABLE_HSDIS_BUNDLING), true) + java.base-copy: build-hsdis + endif + # jdk.accessibility depends on java.desktop jdk.accessibility-libs: java.desktop-libs diff --git a/make/ModuleWrapper.gmk b/make/ModuleWrapper.gmk index e4a8db24aa3c988a7c2885f97140de61be9f3ab7..d83af819a9bc46d053e71cfdac2311b46ea97531 100644 --- a/make/ModuleWrapper.gmk +++ b/make/ModuleWrapper.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 @@ -35,6 +35,8 @@ default: all include $(SPEC) include MakeBase.gmk +MODULE_SRC := $(TOPDIR)/src/$(MODULE) + # All makefiles should add the targets to be built to this variable. TARGETS := diff --git a/make/ToolsJdk.gmk b/make/ToolsJdk.gmk index af9def3a415ad5cf5b00ed12acca94cde7715d4c..9eef6969125a289dfa13760034f6e042bde304e4 100644 --- a/make/ToolsJdk.gmk +++ b/make/ToolsJdk.gmk @@ -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 @@ -53,7 +53,7 @@ TOOL_GENERATECHARACTER = $(JAVA_SMALL) -cp $(BUILDTOOLS_OUTPUTDIR)/jdk_tools_cla TOOL_CHARACTERNAME = $(JAVA_SMALL) -cp $(BUILDTOOLS_OUTPUTDIR)/jdk_tools_classes \ build.tools.generatecharacter.CharacterName -TOOL_DTDBUILDER = $(JAVA_SMALL) -Ddtd_home=$(TOPDIR)/make/data/dtdbuilder \ +TOOL_DTDBUILDER = $(JAVA_SMALL) -Ddtd_home=$(TOPDIR)/src/java.desktop/share/data/dtdbuilder \ -Djava.awt.headless=true \ -cp $(BUILDTOOLS_OUTPUTDIR)/jdk_tools_classes build.tools.dtdbuilder.DTDBuilder diff --git a/make/UpdateX11Wrappers.gmk b/make/UpdateX11Wrappers.gmk index ad67966ec8a7b32f47bbb86d9016e7e70dc3bf0a..3201b5f883f7130d6b874a1fd99bb8038ffb9290 100644 --- a/make/UpdateX11Wrappers.gmk +++ b/make/UpdateX11Wrappers.gmk @@ -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 @@ -50,7 +50,7 @@ endif X11WRAPPERS_OUTPUT := $(SUPPORT_OUTPUTDIR)/x11wrappers GENERATOR_SOURCE_FILE := $(X11WRAPPERS_OUTPUT)/src/data_generator.c -GENSRC_X11WRAPPERS_DATADIR := $(TOPDIR)/make/data/x11wrappergen +GENSRC_X11WRAPPERS_DATADIR := $(TOPDIR)/src/java.desktop/unix/data/x11wrappergen WRAPPER_OUTPUT_FILE := $(GENSRC_X11WRAPPERS_DATADIR)/sizes-$(BITS).txt BITS := $(OPENJDK_TARGET_CPU_BITS) diff --git a/make/autoconf/basic_tools.m4 b/make/autoconf/basic_tools.m4 index 9ce90303d452d5f9705d9e195b0f5e6d59fff808..1611e9fd5312ee8ceb46f1a35cdaf926700daf70 100644 --- a/make/autoconf/basic_tools.m4 +++ b/make/autoconf/basic_tools.m4 @@ -80,6 +80,7 @@ AC_DEFUN_ONCE([BASIC_SETUP_FUNDAMENTAL_TOOLS], # Optional tools, we can do without them UTIL_LOOKUP_PROGS(DF, df) + UTIL_LOOKUP_PROGS(GIT, git) UTIL_LOOKUP_PROGS(NICE, nice) UTIL_LOOKUP_PROGS(READLINK, greadlink readlink) @@ -339,7 +340,6 @@ AC_DEFUN_ONCE([BASIC_SETUP_COMPLEX_TOOLS], UTIL_LOOKUP_PROGS(READELF, greadelf readelf) UTIL_LOOKUP_PROGS(DOT, dot) UTIL_LOOKUP_PROGS(HG, hg) - UTIL_LOOKUP_PROGS(GIT, git) UTIL_LOOKUP_PROGS(STAT, stat) UTIL_LOOKUP_PROGS(TIME, time) UTIL_LOOKUP_PROGS(FLOCK, flock) diff --git a/make/autoconf/basic_windows.m4 b/make/autoconf/basic_windows.m4 index 25d10d9b8fee848f4cd366dbc2edf4aa22aef508..fb6fc526bfa219d361aae8783dfbc47c98d3bcc6 100644 --- a/make/autoconf/basic_windows.m4 +++ b/make/autoconf/basic_windows.m4 @@ -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 @@ -185,6 +185,16 @@ AC_DEFUN([BASIC_SETUP_PATHS_WINDOWS], AC_MSG_RESULT([unknown]) AC_MSG_WARN([It seems that your find utility is non-standard.]) fi + + if test "x$GIT" != x && test -e $TOPDIR/.git; then + git_autocrlf=`$GIT config core.autocrlf` + if test "x$git_autocrlf" != x && test "x$git_autocrlf" != "xfalse"; then + AC_MSG_NOTICE([Your git configuration does not set core.autocrlf to false.]) + AC_MSG_NOTICE([If you checked out this code using that setting, the build WILL fail.]) + AC_MSG_NOTICE([To correct, run "git config --global core.autocrlf false" and re-clone the repo.]) + AC_MSG_WARN([Code is potentially incorrectly cloned. HIGH RISK of build failure!]) + fi + fi ]) # Verify that the directory is usable on Windows diff --git a/make/autoconf/compare.sh.in b/make/autoconf/compare.sh.in index 1c48f800c8a3430cca9137c19ddb74815505b791..542a516ebc4475cc05d3be52c54e8aedece4b5d0 100644 --- a/make/autoconf/compare.sh.in +++ b/make/autoconf/compare.sh.in @@ -53,7 +53,7 @@ export LDD="@LDD@" export LN="@LN@" export MKDIR="@MKDIR@" export MV="@MV@" -export NM="@GNM@" +export NM="@NM@" export OBJDUMP="@OBJDUMP@" export OTOOL="@OTOOL@" export PRINTF="@PRINTF@" diff --git a/make/autoconf/configure b/make/autoconf/configure index 7e0ece129f4dfb2f9354c7406df590e199c01140..4b26e3d706147fdb04158f5dd3133f130d0c0246 100644 --- a/make/autoconf/configure +++ b/make/autoconf/configure @@ -274,11 +274,11 @@ do # Check for certain autoconf options that require extra action case $conf_option in -build | --build | --buil | --bui | --bu |-build=* | --build=* | --buil=* | --bui=* | --bu=*) - conf_legacy_crosscompile="$conf_legacy_crosscompile $conf_option" ;; + conf_build_set=true ;; -target | --target | --targe | --targ | --tar | --ta | --t | -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) - conf_legacy_crosscompile="$conf_legacy_crosscompile $conf_option" ;; + conf_incompatible_crosscompile="$conf_incompatible_crosscompile $conf_option" ;; -host | --host | --hos | --ho | -host=* | --host=* | --hos=* | --ho=*) - conf_legacy_crosscompile="$conf_legacy_crosscompile $conf_option" ;; + conf_incompatible_crosscompile="$conf_incompatible_crosscompile $conf_option" ;; -help | --help | --hel | --he | -h) conf_print_help=true ;; esac @@ -287,23 +287,30 @@ done # Save the quoted command line CONFIGURE_COMMAND_LINE="${conf_quoted_arguments[@]}" -if test "x$conf_legacy_crosscompile" != "x"; then +if test "x$conf_incompatible_crosscompile" != "x"; then if test "x$conf_openjdk_target" != "x"; then - echo "Error: Specifying --openjdk-target together with autoconf" - echo "legacy cross-compilation flags is not supported." - echo "You specified: --openjdk-target=$conf_openjdk_target and $conf_legacy_crosscompile." - echo "The recommended use is just --openjdk-target." + echo "Error: --openjdk-target was specified together with" + echo "incompatible autoconf cross-compilation flags." + echo "You specified: --openjdk-target=$conf_openjdk_target and $conf_incompatible_crosscompile." + echo "It is recommended that you only use --openjdk-target." exit 1 else - echo "Warning: You are using legacy autoconf cross-compilation flags." - echo "It is recommended that you use --openjdk-target instead." + echo "Warning: You are using misleading autoconf cross-compilation flag(s)." + echo "This is not encouraged as use of such flags during building can" + echo "quickly become confusing." + echo "It is highly recommended that you use --openjdk-target instead." echo "" fi fi if test "x$conf_openjdk_target" != "x"; then - conf_build_platform=`sh $conf_script_dir/build-aux/config.guess` - conf_processed_arguments=("--build=$conf_build_platform" "--host=$conf_openjdk_target" "--target=$conf_openjdk_target" "${conf_processed_arguments[@]}") + conf_processed_arguments=("--host=$conf_openjdk_target" "--target=$conf_openjdk_target" "${conf_processed_arguments[@]}") + + # If --build has been explicitly set don't override that flag with our own + if test "x$conf_build_set" != xtrue; then + conf_build_platform=`sh $conf_script_dir/build-aux/config.guess` + conf_processed_arguments=("--build=$conf_build_platform" "${conf_processed_arguments[@]}") + fi fi # Make configure exit with error on invalid options as default. @@ -341,7 +348,9 @@ Additional (non-autoconf) OpenJDK Options: --openjdk-target=TARGET cross-compile with TARGET as target platform (i.e. the one you will run the resulting binary on). Equivalent to --host=TARGET --target=TARGET - --build= + --build=, or the platform you + have provided if you have explicitly passed + --build to configure --debug-configure Run the configure script with additional debug logging enabled. diff --git a/make/autoconf/configure.ac b/make/autoconf/configure.ac index 29ed3f206aa46722b6b50bbb8d3ed047c764a214..5e58696e34d38a2742c1c75dbd39d9d9bb904189 100644 --- a/make/autoconf/configure.ac +++ b/make/autoconf/configure.ac @@ -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 @@ -152,6 +152,7 @@ BOOTJDK_SETUP_DOCS_REFERENCE_JDK # ############################################################################### +JDKOPT_SETUP_REPRODUCIBLE_BUILD JDKOPT_SETUP_JDK_OPTIONS ############################################################################### @@ -207,7 +208,6 @@ PLATFORM_SETUP_OPENJDK_TARGET_BITS PLATFORM_SETUP_OPENJDK_TARGET_ENDIANNESS # Configure flags for the tools. Need to know if we should build reproducible. -JDKOPT_SETUP_REPRODUCIBLE_BUILD FLAGS_SETUP_FLAGS # Setup debug symbols (need objcopy from the toolchain for that) @@ -249,7 +249,6 @@ JDKOPT_EXCLUDE_TRANSLATIONS JDKOPT_ENABLE_DISABLE_MANPAGES JDKOPT_ENABLE_DISABLE_CDS_ARCHIVE JDKOPT_ENABLE_DISABLE_COMPATIBLE_CDS_ALIGNMENT -JDKOPT_SETUP_HSDIS ############################################################################### # diff --git a/make/autoconf/flags-cflags.m4 b/make/autoconf/flags-cflags.m4 index 76724235ec4d703e431d1672ba244fa2d7f26bc8..2d7732e6c66b668cfd90bc611c4a0d90bb868634 100644 --- a/make/autoconf/flags-cflags.m4 +++ b/make/autoconf/flags-cflags.m4 @@ -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 @@ -496,8 +496,8 @@ AC_DEFUN([FLAGS_SETUP_CFLAGS_HELPER], TOOLCHAIN_CFLAGS_JVM="-qtbtable=full -qtune=balanced \ -qalias=noansi -qstrict -qtls=default -qnortti -qnoeh -qignerrno -qstackprotect" elif test "x$TOOLCHAIN_TYPE" = xmicrosoft; then - TOOLCHAIN_CFLAGS_JVM="-nologo -MD -MP" - TOOLCHAIN_CFLAGS_JDK="-nologo -MD -Zc:wchar_t-" + TOOLCHAIN_CFLAGS_JVM="-nologo -MD -Zc:strictStrings -MP" + TOOLCHAIN_CFLAGS_JDK="-nologo -MD -Zc:strictStrings -Zc:wchar_t-" fi # CFLAGS C language level for JDK sources (hotspot only uses C++) @@ -803,17 +803,19 @@ AC_DEFUN([FLAGS_SETUP_CFLAGS_CPU_DEP], fi AC_SUBST(FILE_MACRO_CFLAGS) + FLAGS_SETUP_BRANCH_PROTECTION + # EXPORT to API CFLAGS_JVM_COMMON="$ALWAYS_CFLAGS_JVM $ALWAYS_DEFINES_JVM \ $TOOLCHAIN_CFLAGS_JVM ${$1_TOOLCHAIN_CFLAGS_JVM} \ $OS_CFLAGS $OS_CFLAGS_JVM $CFLAGS_OS_DEF_JVM $DEBUG_CFLAGS_JVM \ $WARNING_CFLAGS $WARNING_CFLAGS_JVM $JVM_PICFLAG $FILE_MACRO_CFLAGS \ - $REPRODUCIBLE_CFLAGS" + $REPRODUCIBLE_CFLAGS $BRANCH_PROTECTION_CFLAGS" CFLAGS_JDK_COMMON="$ALWAYS_CFLAGS_JDK $ALWAYS_DEFINES_JDK $TOOLCHAIN_CFLAGS_JDK \ $OS_CFLAGS $CFLAGS_OS_DEF_JDK $DEBUG_CFLAGS_JDK $DEBUG_OPTIONS_FLAGS_JDK \ $WARNING_CFLAGS $WARNING_CFLAGS_JDK $DEBUG_SYMBOLS_CFLAGS_JDK \ - $FILE_MACRO_CFLAGS $REPRODUCIBLE_CFLAGS" + $FILE_MACRO_CFLAGS $REPRODUCIBLE_CFLAGS $BRANCH_PROTECTION_CFLAGS" # Use ${$2EXTRA_CFLAGS} to block EXTRA_CFLAGS to be added to build flags. # (Currently we don't have any OPENJDK_BUILD_EXTRA_CFLAGS, but that might @@ -879,3 +881,24 @@ AC_DEFUN([FLAGS_SETUP_GCC6_COMPILER_FLAGS], PREFIX: $2, IF_FALSE: [NO_LIFETIME_DSE_CFLAG=""]) $1_GCC6_CFLAGS="${NO_DELETE_NULL_POINTER_CHECKS_CFLAG} ${NO_LIFETIME_DSE_CFLAG}" ]) + +AC_DEFUN_ONCE([FLAGS_SETUP_BRANCH_PROTECTION], +[ + # Is branch protection available? + BRANCH_PROTECTION_AVAILABLE=false + BRANCH_PROTECTION_FLAG="-mbranch-protection=standard" + + if test "x$OPENJDK_TARGET_CPU" = xaarch64; then + if test "x$TOOLCHAIN_TYPE" = xgcc || test "x$TOOLCHAIN_TYPE" = xclang; then + FLAGS_COMPILER_CHECK_ARGUMENTS(ARGUMENT: [${BRANCH_PROTECTION_FLAG}], + IF_TRUE: [BRANCH_PROTECTION_AVAILABLE=true]) + fi + fi + + BRANCH_PROTECTION_CFLAGS="" + UTIL_ARG_ENABLE(NAME: branch-protection, DEFAULT: false, + RESULT: USE_BRANCH_PROTECTION, AVAILABLE: $BRANCH_PROTECTION_AVAILABLE, + DESC: [enable branch protection when compiling C/C++], + IF_ENABLED: [ BRANCH_PROTECTION_CFLAGS=${BRANCH_PROTECTION_FLAG}]) + AC_SUBST(BRANCH_PROTECTION_CFLAGS) +]) diff --git a/make/autoconf/flags-ldflags.m4 b/make/autoconf/flags-ldflags.m4 index e9d4557f8665ed879976b5ba04791ec106a54b13..457690ac39165621d505458530cf7c8741319e5a 100644 --- a/make/autoconf/flags-ldflags.m4 +++ b/make/autoconf/flags-ldflags.m4 @@ -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 @@ -77,7 +77,7 @@ AC_DEFUN([FLAGS_SETUP_LDFLAGS_HELPER], -fPIC" elif test "x$TOOLCHAIN_TYPE" = xxlc; then - BASIC_LDFLAGS="-b64 -brtl -bnorwexec -bnolibpath -bexpall -bernotok -btextpsize:64K \ + BASIC_LDFLAGS="-b64 -brtl -bnorwexec -bnolibpath -bnoexpall -bernotok -btextpsize:64K \ -bdatapsize:64K -bstackpsize:64K" # libjvm.so has gotten too large for normal TOC size; compile with qpic=large and link with bigtoc BASIC_LDFLAGS_JVM_ONLY="-Wl,-lC_r -bbigtoc" @@ -95,13 +95,10 @@ AC_DEFUN([FLAGS_SETUP_LDFLAGS_HELPER], fi # Setup OS-dependent LDFLAGS - if test "x$TOOLCHAIN_TYPE" = xclang || test "x$TOOLCHAIN_TYPE" = xgcc; then - if test "x$OPENJDK_TARGET_OS" = xmacosx; then - # Assume clang or gcc. - # FIXME: We should really generalize SET_SHARED_LIBRARY_ORIGIN instead. - OS_LDFLAGS_JVM_ONLY="-Wl,-rpath,@loader_path/. -Wl,-rpath,@loader_path/.." - OS_LDFLAGS="-mmacosx-version-min=$MACOSX_VERSION_MIN" - fi + if test "x$OPENJDK_TARGET_OS" = xmacosx && test "x$TOOLCHAIN_TYPE" = xclang; then + # FIXME: We should really generalize SET_SHARED_LIBRARY_ORIGIN instead. + OS_LDFLAGS_JVM_ONLY="-Wl,-rpath,@loader_path/. -Wl,-rpath,@loader_path/.." + OS_LDFLAGS="-mmacosx-version-min=$MACOSX_VERSION_MIN" fi # Setup debug level-dependent LDFLAGS diff --git a/make/autoconf/help.m4 b/make/autoconf/help.m4 index 09e82e36c94cd3ba3e1391e3b3703ca3cacb445a..3d6963c7d4d09553d115d335161a6aae76bb0894 100644 --- a/make/autoconf/help.m4 +++ b/make/autoconf/help.m4 @@ -117,6 +117,8 @@ apt_help() { PKGHANDLER_COMMAND="sudo apt-get install ccache" ;; dtrace) PKGHANDLER_COMMAND="sudo apt-get install systemtap-sdt-dev" ;; + capstone) + PKGHANDLER_COMMAND="sudo apt-get install libcapstone-dev" ;; esac } @@ -168,6 +170,8 @@ brew_help() { PKGHANDLER_COMMAND="brew install freetype" ;; ccache) PKGHANDLER_COMMAND="brew install ccache" ;; + capstone) + PKGHANDLER_COMMAND="brew install capstone" ;; esac } @@ -292,6 +296,13 @@ AC_DEFUN_ONCE([HELP_PRINT_SUMMARY_AND_WARNINGS], printf "* OpenJDK target: OS: $OPENJDK_TARGET_OS, CPU architecture: $OPENJDK_TARGET_CPU_ARCH, address length: $OPENJDK_TARGET_CPU_BITS\n" printf "* Version string: $VERSION_STRING ($VERSION_SHORT)\n" + if test "x$SOURCE_DATE" != xupdated; then + source_date_info="$SOURCE_DATE ($SOURCE_DATE_ISO_8601)" + else + source_date_info="Determined at build time" + fi + printf "* Source date: $source_date_info\n" + printf "\n" printf "Tools summary:\n" if test "x$OPENJDK_BUILD_OS" = "xwindows"; then diff --git a/make/autoconf/hotspot.m4 b/make/autoconf/hotspot.m4 index 1cac6bb00c666e814d2e8cfd557661d0327d1d06..18f46036fe5243f940e2f6d2884ed9cdd211791b 100644 --- a/make/autoconf/hotspot.m4 +++ b/make/autoconf/hotspot.m4 @@ -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 @@ -114,12 +114,26 @@ AC_DEFUN_ONCE([HOTSPOT_SETUP_MISC], HOTSPOT_TARGET_CPU_ARCH=zero fi + AC_ARG_WITH([hotspot-build-time], [AS_HELP_STRING([--with-hotspot-build-time], - [timestamp to use in hotspot version string, empty for on-the-fly @<:@empty@:>@])]) + [timestamp to use in hotspot version string, empty means determined at build time @<:@source-date/empty@:>@])]) + + AC_MSG_CHECKING([what hotspot build time to use]) if test "x$with_hotspot_build_time" != x; then HOTSPOT_BUILD_TIME="$with_hotspot_build_time" + AC_MSG_RESULT([$HOTSPOT_BUILD_TIME (from --with-hotspot-build-time)]) + else + if test "x$SOURCE_DATE" = xupdated; then + HOTSPOT_BUILD_TIME="" + AC_MSG_RESULT([determined at build time (default)]) + else + # If we have a fixed value for SOURCE_DATE, use it as default + HOTSPOT_BUILD_TIME="$SOURCE_DATE_ISO_8601" + AC_MSG_RESULT([$HOTSPOT_BUILD_TIME (from --with-source-date)]) + fi fi + AC_SUBST(HOTSPOT_BUILD_TIME) diff --git a/make/autoconf/jdk-options.m4 b/make/autoconf/jdk-options.m4 index 0a7145c9116a4f4d90f1e9f354c7b78aef25a7b6..2034934cd733241d48ce87044269cb6fc0c06c75 100644 --- a/make/autoconf/jdk-options.m4 +++ b/make/autoconf/jdk-options.m4 @@ -211,16 +211,16 @@ AC_DEFUN_ONCE([JDKOPT_SETUP_JDK_OPTIONS], # Setup default copyright year. Mostly overridden when building close to a new year. AC_ARG_WITH(copyright-year, [AS_HELP_STRING([--with-copyright-year], - [Set copyright year value for build @<:@current year@:>@])]) + [Set copyright year value for build @<:@current year/source-date@:>@])]) if test "x$with_copyright_year" = xyes; then AC_MSG_ERROR([Copyright year must have a value]) elif test "x$with_copyright_year" != x; then COPYRIGHT_YEAR="$with_copyright_year" - elif test "x$SOURCE_DATE_EPOCH" != x; then + elif test "x$SOURCE_DATE" != xupdated; then if test "x$IS_GNU_DATE" = xyes; then - COPYRIGHT_YEAR=`date --date=@$SOURCE_DATE_EPOCH +%Y` + COPYRIGHT_YEAR=`$DATE --date=@$SOURCE_DATE +%Y` else - COPYRIGHT_YEAR=`date -j -f %s $SOURCE_DATE_EPOCH +%Y` + COPYRIGHT_YEAR=`$DATE -j -f %s $SOURCE_DATE +%Y` fi else COPYRIGHT_YEAR=`$DATE +'%Y'` @@ -662,15 +662,28 @@ AC_DEFUN([JDKOPT_ALLOW_ABSOLUTE_PATHS_IN_OUTPUT], AC_DEFUN_ONCE([JDKOPT_SETUP_REPRODUCIBLE_BUILD], [ AC_ARG_WITH([source-date], [AS_HELP_STRING([--with-source-date], - [how to set SOURCE_DATE_EPOCH ('updated', 'current', 'version' a timestamp or an ISO-8601 date) @<:@updated@:>@])], + [how to set SOURCE_DATE_EPOCH ('updated', 'current', 'version' a timestamp or an ISO-8601 date) @<:@updated/value of SOURCE_DATE_EPOCH@:>@])], [with_source_date_present=true], [with_source_date_present=false]) + if test "x$SOURCE_DATE_EPOCH" != x && test "x$with_source_date" != x; then + AC_MSG_WARN([--with-source-date will override SOURCE_DATE_EPOCH]) + fi + AC_MSG_CHECKING([what source date to use]) if test "x$with_source_date" = xyes; then AC_MSG_ERROR([--with-source-date must have a value]) - elif test "x$with_source_date" = xupdated || test "x$with_source_date" = x; then - # Tell the makefiles to update at each build + elif test "x$with_source_date" = x; then + if test "x$SOURCE_DATE_EPOCH" != x; then + SOURCE_DATE=$SOURCE_DATE_EPOCH + with_source_date_present=true + AC_MSG_RESULT([$SOURCE_DATE, from SOURCE_DATE_EPOCH]) + else + # Tell the makefiles to update at each build + SOURCE_DATE=updated + AC_MSG_RESULT([determined at build time (default)]) + fi + elif test "x$with_source_date" = xupdated; then SOURCE_DATE=updated AC_MSG_RESULT([determined at build time, from 'updated']) elif test "x$with_source_date" = xcurrent; then @@ -702,6 +715,18 @@ AC_DEFUN_ONCE([JDKOPT_SETUP_REPRODUCIBLE_BUILD], fi fi + ISO_8601_FORMAT_STRING="%Y-%m-%dT%H:%M:%SZ" + if test "x$SOURCE_DATE" != xupdated; then + # If we have a fixed value for SOURCE_DATE, we need to set SOURCE_DATE_EPOCH + # for the rest of configure. + SOURCE_DATE_EPOCH="$SOURCE_DATE" + if test "x$IS_GNU_DATE" = xyes; then + SOURCE_DATE_ISO_8601=`$DATE --utc --date="@$SOURCE_DATE" +"$ISO_8601_FORMAT_STRING" 2> /dev/null` + else + SOURCE_DATE_ISO_8601=`$DATE -u -j -f "%s" "$SOURCE_DATE" +"$ISO_8601_FORMAT_STRING" 2> /dev/null` + fi + fi + REPRODUCIBLE_BUILD_DEFAULT=$with_source_date_present if test "x$OPENJDK_BUILD_OS" = xwindows && \ @@ -726,174 +751,6 @@ AC_DEFUN_ONCE([JDKOPT_SETUP_REPRODUCIBLE_BUILD], AC_SUBST(SOURCE_DATE) AC_SUBST(ENABLE_REPRODUCIBLE_BUILD) -]) - -################################################################################ -# -# Helper function to build binutils from source. -# -AC_DEFUN([JDKOPT_BUILD_BINUTILS], -[ - BINUTILS_SRC="$with_binutils_src" - UTIL_FIXUP_PATH(BINUTILS_SRC) - - if ! test -d $BINUTILS_SRC; then - AC_MSG_ERROR([--with-binutils-src is not pointing to a directory]) - fi - if ! test -x $BINUTILS_SRC/configure; then - AC_MSG_ERROR([--with-binutils-src does not look like a binutils source directory]) - fi - - if test -e $BINUTILS_SRC/bfd/libbfd.a && \ - test -e $BINUTILS_SRC/opcodes/libopcodes.a && \ - test -e $BINUTILS_SRC/libiberty/libiberty.a && \ - test -e $BINUTILS_SRC/zlib/libz.a; then - AC_MSG_NOTICE([Found binutils binaries in binutils source directory -- not building]) - else - # On Windows, we cannot build with the normal Microsoft CL, but must instead use - # a separate mingw toolchain. - if test "x$OPENJDK_BUILD_OS" = xwindows; then - if test "x$OPENJDK_TARGET_CPU" = "xx86"; then - target_base="i686-w64-mingw32" - else - target_base="$OPENJDK_TARGET_CPU-w64-mingw32" - fi - binutils_cc="$target_base-gcc" - binutils_target="--host=$target_base --target=$target_base" - # Somehow the uint typedef is not included when building with mingw - binutils_cflags="-Duint=unsigned" - compiler_version=`$binutils_cc --version 2>&1` - if ! [ [[ "$compiler_version" =~ GCC ]] ]; then - AC_MSG_NOTICE([Could not find correct mingw compiler $binutils_cc.]) - HELP_MSG_MISSING_DEPENDENCY([$binutils_cc]) - AC_MSG_ERROR([Cannot continue. $HELP_MSG]) - else - AC_MSG_NOTICE([Using compiler $binutils_cc with version $compiler_version]) - fi - elif test "x$OPENJDK_BUILD_OS" = xmacosx; then - if test "x$OPENJDK_TARGET_CPU" = "xaarch64"; then - binutils_target="--enable-targets=aarch64-darwin" - else - binutils_target="" - fi - else - binutils_cc="$CC $SYSROOT_CFLAGS" - binutils_target="" - fi - binutils_cflags="$binutils_cflags $MACHINE_FLAG $JVM_PICFLAG $C_O_FLAG_NORM" - - AC_MSG_NOTICE([Running binutils configure]) - AC_MSG_NOTICE([configure command line: ./configure --disable-nls CFLAGS="$binutils_cflags" CC="$binutils_cc" $binutils_target]) - saved_dir=`pwd` - cd "$BINUTILS_SRC" - ./configure --disable-nls CFLAGS="$binutils_cflags" CC="$binutils_cc" $binutils_target - if test $? -ne 0 || ! test -e $BINUTILS_SRC/Makefile; then - AC_MSG_NOTICE([Automatic building of binutils failed on configure. Try building it manually]) - AC_MSG_ERROR([Cannot continue]) - fi - AC_MSG_NOTICE([Running binutils make]) - $MAKE all-opcodes - if test $? -ne 0; then - AC_MSG_NOTICE([Automatic building of binutils failed on make. Try building it manually]) - AC_MSG_ERROR([Cannot continue]) - fi - cd $saved_dir - AC_MSG_NOTICE([Building of binutils done]) - fi - - BINUTILS_DIR="$BINUTILS_SRC" -]) - -################################################################################ -# -# Determine if hsdis should be built, and if so, with which backend. -# -AC_DEFUN_ONCE([JDKOPT_SETUP_HSDIS], -[ - AC_ARG_WITH([hsdis], [AS_HELP_STRING([--with-hsdis], - [what hsdis backend to use ('none', 'binutils') @<:@none@:>@])]) - - AC_ARG_WITH([binutils], [AS_HELP_STRING([--with-binutils], - [where to find the binutils files needed for hsdis/binutils])]) - - AC_ARG_WITH([binutils-src], [AS_HELP_STRING([--with-binutils-src], - [where to find the binutils source for building])]) - - AC_MSG_CHECKING([what hsdis backend to use]) - - if test "x$with_hsdis" = xyes; then - AC_MSG_ERROR([--with-hsdis must have a value]) - elif test "x$with_hsdis" = xnone || test "x$with_hsdis" = xno || test "x$with_hsdis" = x; then - HSDIS_BACKEND=none - AC_MSG_RESULT(['none', hsdis will not be built]) - elif test "x$with_hsdis" = xbinutils; then - HSDIS_BACKEND=binutils - AC_MSG_RESULT(['binutils']) - - # We need the binutils static libs and includes. - if test "x$with_binutils_src" != x; then - # Try building the source first. If it succeeds, it sets $BINUTILS_DIR. - JDKOPT_BUILD_BINUTILS - fi - - if test "x$with_binutils" != x; then - BINUTILS_DIR="$with_binutils" - fi - - binutils_system_error="" - HSDIS_LIBS="" - if test "x$BINUTILS_DIR" = xsystem; then - AC_CHECK_LIB(bfd, bfd_openr, [ HSDIS_LIBS="-lbfd" ], [ binutils_system_error="libbfd not found" ]) - AC_CHECK_LIB(opcodes, disassembler, [ HSDIS_LIBS="$HSDIS_LIBS -lopcodes" ], [ binutils_system_error="libopcodes not found" ]) - AC_CHECK_LIB(iberty, xmalloc, [ HSDIS_LIBS="$HSDIS_LIBS -liberty" ], [ binutils_system_error="libiberty not found" ]) - AC_CHECK_LIB(z, deflate, [ HSDIS_LIBS="$HSDIS_LIBS -lz" ], [ binutils_system_error="libz not found" ]) - HSDIS_CFLAGS="-DLIBARCH_$OPENJDK_TARGET_CPU_LEGACY_LIB" - elif test "x$BINUTILS_DIR" != x; then - if test -e $BINUTILS_DIR/bfd/libbfd.a && \ - test -e $BINUTILS_DIR/opcodes/libopcodes.a && \ - test -e $BINUTILS_DIR/libiberty/libiberty.a; then - HSDIS_CFLAGS="-I$BINUTILS_DIR/include -I$BINUTILS_DIR/bfd -DLIBARCH_$OPENJDK_TARGET_CPU_LEGACY_LIB" - HSDIS_LIBS="$BINUTILS_DIR/bfd/libbfd.a $BINUTILS_DIR/opcodes/libopcodes.a $BINUTILS_DIR/libiberty/libiberty.a $BINUTILS_DIR/zlib/libz.a" - fi - fi - - AC_MSG_CHECKING([for binutils to use with hsdis]) - case "x$BINUTILS_DIR" in - xsystem) - if test "x$OPENJDK_TARGET_OS" != xlinux; then - AC_MSG_RESULT([invalid]) - AC_MSG_ERROR([binutils on system is supported for Linux only]) - elif test "x$binutils_system_error" = x; then - AC_MSG_RESULT([system]) - HSDIS_CFLAGS="$HSDIS_CFLAGS -DSYSTEM_BINUTILS" - else - AC_MSG_RESULT([invalid]) - AC_MSG_ERROR([$binutils_system_error]) - fi - ;; - x) - AC_MSG_RESULT([missing]) - AC_MSG_NOTICE([--with-hsdis=binutils requires specifying a binutils installation.]) - AC_MSG_NOTICE([Download binutils from https://www.gnu.org/software/binutils and unpack it,]) - AC_MSG_NOTICE([and point --with-binutils-src to the resulting directory, or use]) - AC_MSG_NOTICE([--with-binutils to point to a pre-built binutils installation.]) - AC_MSG_ERROR([Cannot continue]) - ;; - *) - if test "x$HSDIS_LIBS" != x; then - AC_MSG_RESULT([$BINUTILS_DIR]) - else - AC_MSG_RESULT([invalid]) - AC_MSG_ERROR([$BINUTILS_DIR does not contain a proper binutils installation]) - fi - ;; - esac - else - AC_MSG_RESULT([invalid]) - AC_MSG_ERROR([Incorrect hsdis backend "$with_hsdis"]) - fi - - AC_SUBST(HSDIS_BACKEND) - AC_SUBST(HSDIS_CFLAGS) - AC_SUBST(HSDIS_LIBS) + AC_SUBST(ISO_8601_FORMAT_STRING) + AC_SUBST(SOURCE_DATE_ISO_8601) ]) diff --git a/make/autoconf/jdk-version.m4 b/make/autoconf/jdk-version.m4 index 5e64ce9a064f86e2ee6a46e8ec86a108f60f31e4..41f4b1fb1211f77b68b4b1f17c3893d94abc0d89 100644 --- a/make/autoconf/jdk-version.m4 +++ b/make/autoconf/jdk-version.m4 @@ -72,7 +72,9 @@ AC_DEFUN_ONCE([JDKVER_SETUP_JDK_VERSION_NUMBERS], # 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" != x; then + 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. @@ -84,7 +86,7 @@ AC_DEFUN_ONCE([JDKVER_SETUP_JDK_VERSION_NUMBERS], 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; then + 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]) @@ -101,7 +103,7 @@ AC_DEFUN_ONCE([JDKVER_SETUP_JDK_VERSION_NUMBERS], 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; then + 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]) @@ -115,7 +117,7 @@ AC_DEFUN_ONCE([JDKVER_SETUP_JDK_VERSION_NUMBERS], # 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; then + 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]) @@ -129,7 +131,7 @@ AC_DEFUN_ONCE([JDKVER_SETUP_JDK_VERSION_NUMBERS], # 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; then + 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]) @@ -143,7 +145,7 @@ AC_DEFUN_ONCE([JDKVER_SETUP_JDK_VERSION_NUMBERS], # 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; then + 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]) @@ -160,7 +162,7 @@ AC_DEFUN_ONCE([JDKVER_SETUP_JDK_VERSION_NUMBERS], # 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; then + 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. @@ -293,7 +295,7 @@ AC_DEFUN_ONCE([JDKVER_SETUP_JDK_VERSION_NUMBERS], [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; 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) @@ -480,7 +482,7 @@ AC_DEFUN_ONCE([JDKVER_SETUP_JDK_VERSION_NUMBERS], # 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; then + 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 @@ -499,7 +501,10 @@ AC_DEFUN_ONCE([JDKVER_SETUP_JDK_VERSION_NUMBERS], 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]) - else + 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" fi @@ -507,7 +512,7 @@ AC_DEFUN_ONCE([JDKVER_SETUP_JDK_VERSION_NUMBERS], 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; then + 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]) @@ -521,7 +526,7 @@ AC_DEFUN_ONCE([JDKVER_SETUP_JDK_VERSION_NUMBERS], 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; then + 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]) @@ -542,14 +547,19 @@ AC_DEFUN_ONCE([JDKVER_SETUP_JDK_VERSION_NUMBERS], [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; then + 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" else - MACOSX_BUNDLE_BUILD_VERSION="$VERSION_BUILD" + if test "x$VERSION_BUILD" != x; then + MACOSX_BUNDLE_BUILD_VERSION="$VERSION_BUILD" + else + 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" diff --git a/make/autoconf/lib-hsdis.m4 b/make/autoconf/lib-hsdis.m4 new file mode 100644 index 0000000000000000000000000000000000000000..f3e5da5f8690199cb86b1e4412e7e7ce19fc917c --- /dev/null +++ b/make/autoconf/lib-hsdis.m4 @@ -0,0 +1,336 @@ +# +# 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. 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. +# + +################################################################################ +# +# Helper function to setup hsdis using Capstone +# +AC_DEFUN([LIB_SETUP_HSDIS_CAPSTONE], +[ + AC_ARG_WITH(capstone, [AS_HELP_STRING([--with-capstone], + [where to find the Capstone files needed for hsdis/capstone])]) + + if test "x$with_capstone" != x; then + AC_MSG_CHECKING([for capstone]) + CAPSTONE="$with_capstone" + AC_MSG_RESULT([$CAPSTONE]) + + HSDIS_CFLAGS="-I${CAPSTONE}/include/capstone" + if test "x$OPENJDK_TARGET_OS" != xwindows; then + HSDIS_LDFLAGS="-L${CAPSTONE}/lib" + HSDIS_LIBS="-lcapstone" + else + HSDIS_LDFLAGS="-nodefaultlib:libcmt.lib" + HSDIS_LIBS="${CAPSTONE}/capstone.lib" + fi + else + if test "x$OPENJDK_TARGET_OS" = xwindows; then + # There is no way to auto-detect capstone on Windowos + AC_MSG_NOTICE([You must specify capstone location using --with-capstone=]) + AC_MSG_ERROR([Cannot continue]) + fi + + PKG_CHECK_MODULES(CAPSTONE, capstone, [CAPSTONE_FOUND=yes], [CAPSTONE_FOUND=no]) + if test "x$CAPSTONE_FOUND" = xyes; then + HSDIS_CFLAGS="$CAPSTONE_CFLAGS" + HSDIS_LDFLAGS="$CAPSTONE_LDFLAGS" + HSDIS_LIBS="$CAPSTONE_LIBS" + else + HELP_MSG_MISSING_DEPENDENCY([capstone]) + AC_MSG_NOTICE([Cannot locate capstone which is needed for hsdis/capstone. Try using --with-capstone=. $HELP_MSG]) + AC_MSG_ERROR([Cannot continue]) + fi + fi +]) + +################################################################################ +# +# Helper function to setup hsdis using LLVM +# +AC_DEFUN([LIB_SETUP_HSDIS_LLVM], +[ + AC_ARG_WITH([llvm], [AS_HELP_STRING([--with-llvm], + [where to find the LLVM files needed for hsdis/llvm])]) + + if test "x$with_llvm" != x; then + LLVM_DIR="$with_llvm" + fi + + if test "x$OPENJDK_TARGET_OS" != xwindows; then + if test "x$LLVM_DIR" = x; then + # Macs with homebrew can have llvm in different places + UTIL_LOOKUP_PROGS(LLVM_CONFIG, llvm-config, [$PATH:/usr/local/opt/llvm/bin:/opt/homebrew/opt/llvm/bin]) + if test "x$LLVM_CONFIG" = x; then + AC_MSG_NOTICE([Cannot locate llvm-config which is needed for hsdis/llvm. Try using --with-llvm=.]) + AC_MSG_ERROR([Cannot continue]) + fi + else + UTIL_LOOKUP_PROGS(LLVM_CONFIG, llvm-config, [$LLVM_DIR/bin]) + if test "x$LLVM_CONFIG" = x; then + AC_MSG_NOTICE([Cannot locate llvm-config in $LLVM_DIR. Check your --with-llvm argument.]) + AC_MSG_ERROR([Cannot continue]) + fi + fi + + # We need the LLVM flags and libs, and llvm-config provides them for us. + HSDIS_CFLAGS=`$LLVM_CONFIG --cflags` + HSDIS_LDFLAGS=`$LLVM_CONFIG --ldflags` + HSDIS_LIBS=`$LLVM_CONFIG --libs $OPENJDK_TARGET_CPU_ARCH ${OPENJDK_TARGET_CPU_ARCH}disassembler` + else + if test "x$LLVM_DIR" = x; then + AC_MSG_NOTICE([--with-llvm is needed on Windows to point out the LLVM home]) + AC_MSG_ERROR([Cannot continue]) + fi + + # Official Windows installation of LLVM do not ship llvm-config, and self-built llvm-config + # produced unusable output, so just ignore it on Windows. + if ! test -e $LLVM_DIR/include/llvm-c/lto.h; then + AC_MSG_NOTICE([$LLVM_DIR does not seem like a valid LLVM home; include dir is missing]) + AC_MSG_ERROR([Cannot continue]) + fi + if ! test -e $LLVM_DIR/include/llvm-c/Disassembler.h; then + AC_MSG_NOTICE([$LLVM_DIR does not point to a complete LLVM installation. ]) + AC_MSG_NOTICE([The official LLVM distribution is missing crucical files; you need to build LLVM yourself or get all include files elsewhere]) + AC_MSG_ERROR([Cannot continue]) + fi + if ! test -e $LLVM_DIR/lib/llvm-c.lib; then + AC_MSG_NOTICE([$LLVM_DIR does not seem like a valid LLVM home; lib dir is missing]) + AC_MSG_ERROR([Cannot continue]) + fi + HSDIS_CFLAGS="-I$LLVM_DIR/include" + HSDIS_LDFLAGS="-libpath:$LLVM_DIR/lib" + HSDIS_LIBS="llvm-c.lib" + fi +]) + +################################################################################ +# +# Helper function to build binutils from source. +# +AC_DEFUN([LIB_BUILD_BINUTILS], +[ + BINUTILS_SRC="$with_binutils_src" + UTIL_FIXUP_PATH(BINUTILS_SRC) + + if ! test -d $BINUTILS_SRC; then + AC_MSG_ERROR([--with-binutils-src is not pointing to a directory]) + fi + if ! test -x $BINUTILS_SRC/configure; then + AC_MSG_ERROR([--with-binutils-src does not look like a binutils source directory]) + fi + + if test -e $BINUTILS_SRC/bfd/libbfd.a && \ + test -e $BINUTILS_SRC/opcodes/libopcodes.a && \ + test -e $BINUTILS_SRC/libiberty/libiberty.a && \ + test -e $BINUTILS_SRC/zlib/libz.a; then + AC_MSG_NOTICE([Found binutils binaries in binutils source directory -- not building]) + else + # On Windows, we cannot build with the normal Microsoft CL, but must instead use + # a separate mingw toolchain. + if test "x$OPENJDK_BUILD_OS" = xwindows; then + if test "x$OPENJDK_TARGET_CPU" = "xx86"; then + target_base="i686-w64-mingw32" + else + target_base="$OPENJDK_TARGET_CPU-w64-mingw32" + fi + binutils_cc="$target_base-gcc" + binutils_target="--host=$target_base --target=$target_base" + # Somehow the uint typedef is not included when building with mingw + binutils_cflags="-Duint=unsigned" + compiler_version=`$binutils_cc --version 2>&1` + if ! [ [[ "$compiler_version" =~ GCC ]] ]; then + AC_MSG_NOTICE([Could not find correct mingw compiler $binutils_cc.]) + HELP_MSG_MISSING_DEPENDENCY([$binutils_cc]) + AC_MSG_ERROR([Cannot continue. $HELP_MSG]) + else + AC_MSG_NOTICE([Using compiler $binutils_cc with version $compiler_version]) + fi + elif test "x$OPENJDK_BUILD_OS" = xmacosx; then + if test "x$OPENJDK_TARGET_CPU" = "xaarch64"; then + binutils_target="--enable-targets=aarch64-darwin" + else + binutils_target="" + fi + else + binutils_cc="$CC $SYSROOT_CFLAGS" + binutils_target="" + fi + binutils_cflags="$binutils_cflags $MACHINE_FLAG $JVM_PICFLAG $C_O_FLAG_NORM" + + AC_MSG_NOTICE([Running binutils configure]) + AC_MSG_NOTICE([configure command line: ./configure --disable-nls CFLAGS="$binutils_cflags" CC="$binutils_cc" $binutils_target]) + saved_dir=`pwd` + cd "$BINUTILS_SRC" + ./configure --disable-nls CFLAGS="$binutils_cflags" CC="$binutils_cc" $binutils_target + if test $? -ne 0 || ! test -e $BINUTILS_SRC/Makefile; then + AC_MSG_NOTICE([Automatic building of binutils failed on configure. Try building it manually]) + AC_MSG_ERROR([Cannot continue]) + fi + AC_MSG_NOTICE([Running binutils make]) + $MAKE all-opcodes + if test $? -ne 0; then + AC_MSG_NOTICE([Automatic building of binutils failed on make. Try building it manually]) + AC_MSG_ERROR([Cannot continue]) + fi + cd $saved_dir + AC_MSG_NOTICE([Building of binutils done]) + fi + + BINUTILS_DIR="$BINUTILS_SRC" +]) + +################################################################################ +# +# Helper function to setup hsdis using binutils +# +AC_DEFUN([LIB_SETUP_HSDIS_BINUTILS], +[ + AC_ARG_WITH([binutils], [AS_HELP_STRING([--with-binutils], + [where to find the binutils files needed for hsdis/binutils])]) + + AC_ARG_WITH([binutils-src], [AS_HELP_STRING([--with-binutils-src], + [where to find the binutils source for building])]) + + # We need the binutils static libs and includes. + if test "x$with_binutils_src" != x; then + # Try building the source first. If it succeeds, it sets $BINUTILS_DIR. + LIB_BUILD_BINUTILS + fi + + if test "x$with_binutils" != x; then + BINUTILS_DIR="$with_binutils" + fi + + binutils_system_error="" + HSDIS_LIBS="" + if test "x$BINUTILS_DIR" = xsystem; then + AC_CHECK_LIB(bfd, bfd_openr, [ HSDIS_LIBS="-lbfd" ], [ binutils_system_error="libbfd not found" ]) + AC_CHECK_LIB(opcodes, disassembler, [ HSDIS_LIBS="$HSDIS_LIBS -lopcodes" ], [ binutils_system_error="libopcodes not found" ]) + AC_CHECK_LIB(iberty, xmalloc, [ HSDIS_LIBS="$HSDIS_LIBS -liberty" ], [ binutils_system_error="libiberty not found" ]) + AC_CHECK_LIB(z, deflate, [ HSDIS_LIBS="$HSDIS_LIBS -lz" ], [ binutils_system_error="libz not found" ]) + HSDIS_CFLAGS="-DLIBARCH_$OPENJDK_TARGET_CPU_LEGACY_LIB" + elif test "x$BINUTILS_DIR" != x; then + if test -e $BINUTILS_DIR/bfd/libbfd.a && \ + test -e $BINUTILS_DIR/opcodes/libopcodes.a && \ + test -e $BINUTILS_DIR/libiberty/libiberty.a; then + HSDIS_CFLAGS="-I$BINUTILS_DIR/include -I$BINUTILS_DIR/bfd -DLIBARCH_$OPENJDK_TARGET_CPU_LEGACY_LIB" + HSDIS_LDFLAGS="" + HSDIS_LIBS="$BINUTILS_DIR/bfd/libbfd.a $BINUTILS_DIR/opcodes/libopcodes.a $BINUTILS_DIR/libiberty/libiberty.a $BINUTILS_DIR/zlib/libz.a" + fi + fi + + AC_MSG_CHECKING([for binutils to use with hsdis]) + case "x$BINUTILS_DIR" in + xsystem) + if test "x$OPENJDK_TARGET_OS" != xlinux; then + AC_MSG_RESULT([invalid]) + AC_MSG_ERROR([binutils on system is supported for Linux only]) + elif test "x$binutils_system_error" = x; then + AC_MSG_RESULT([system]) + HSDIS_CFLAGS="$HSDIS_CFLAGS -DSYSTEM_BINUTILS" + else + AC_MSG_RESULT([invalid]) + AC_MSG_ERROR([$binutils_system_error]) + fi + ;; + x) + AC_MSG_RESULT([missing]) + AC_MSG_NOTICE([--with-hsdis=binutils requires specifying a binutils installation.]) + AC_MSG_NOTICE([Download binutils from https://www.gnu.org/software/binutils and unpack it,]) + AC_MSG_NOTICE([and point --with-binutils-src to the resulting directory, or use]) + AC_MSG_NOTICE([--with-binutils to point to a pre-built binutils installation.]) + AC_MSG_ERROR([Cannot continue]) + ;; + *) + if test "x$HSDIS_LIBS" != x; then + AC_MSG_RESULT([$BINUTILS_DIR]) + else + AC_MSG_RESULT([invalid]) + AC_MSG_ERROR([$BINUTILS_DIR does not contain a proper binutils installation]) + fi + ;; + esac +]) + +################################################################################ +# +# Determine if hsdis should be built, and if so, with which backend. +# +AC_DEFUN_ONCE([LIB_SETUP_HSDIS], +[ + AC_ARG_WITH([hsdis], [AS_HELP_STRING([--with-hsdis], + [what hsdis backend to use ('none', 'capstone', 'llvm', 'binutils') @<:@none@:>@])]) + + UTIL_ARG_ENABLE(NAME: hsdis-bundling, DEFAULT: false, + RESULT: ENABLE_HSDIS_BUNDLING, + DESC: [enable bundling of hsdis to allow HotSpot disassembly out-of-the-box]) + + AC_MSG_CHECKING([what hsdis backend to use]) + + if test "x$with_hsdis" = xyes; then + AC_MSG_ERROR([--with-hsdis must have a value]) + elif test "x$with_hsdis" = xnone || test "x$with_hsdis" = xno || test "x$with_hsdis" = x; then + HSDIS_BACKEND=none + AC_MSG_RESULT(['none', hsdis will not be built]) + elif test "x$with_hsdis" = xcapstone; then + HSDIS_BACKEND=capstone + AC_MSG_RESULT(['capstone']) + + LIB_SETUP_HSDIS_CAPSTONE + elif test "x$with_hsdis" = xllvm; then + HSDIS_BACKEND=llvm + AC_MSG_RESULT(['llvm']) + + LIB_SETUP_HSDIS_LLVM + elif test "x$with_hsdis" = xbinutils; then + HSDIS_BACKEND=binutils + AC_MSG_RESULT(['binutils']) + + LIB_SETUP_HSDIS_BINUTILS + else + AC_MSG_RESULT([invalid]) + AC_MSG_ERROR([Incorrect hsdis backend "$with_hsdis"]) + fi + + AC_SUBST(HSDIS_BACKEND) + AC_SUBST(HSDIS_CFLAGS) + AC_SUBST(HSDIS_LDFLAGS) + AC_SUBST(HSDIS_LIBS) + + AC_MSG_CHECKING([if hsdis should be bundled]) + if test "x$ENABLE_HSDIS_BUNDLING" = "xtrue"; then + if test "x$HSDIS_BACKEND" = xnone; then + AC_MSG_RESULT([no, backend missing]) + AC_MSG_ERROR([hsdis-bundling requires a hsdis backend. Please set --with-hsdis=]); + fi + AC_MSG_RESULT([yes]) + if test "x$HSDIS_BACKEND" = xbinutils; then + AC_MSG_WARN([The resulting build might not be redistributable. Seek legal advice before distributing.]) + fi + else + AC_MSG_RESULT([no]) + fi + AC_SUBST(ENABLE_HSDIS_BUNDLING) +]) diff --git a/make/autoconf/libraries.m4 b/make/autoconf/libraries.m4 index 8e4012910d890774acb9a2769c147e1b14f9951e..fbc8ee7b9c8638fd639e3c34076a25bbce04dc4c 100644 --- a/make/autoconf/libraries.m4 +++ b/make/autoconf/libraries.m4 @@ -28,10 +28,12 @@ m4_include([lib-alsa.m4]) m4_include([lib-bundled.m4]) m4_include([lib-cups.m4]) m4_include([lib-ffi.m4]) +m4_include([lib-fontconfig.m4]) m4_include([lib-freetype.m4]) +m4_include([lib-hsdis.m4]) m4_include([lib-std.m4]) m4_include([lib-x11.m4]) -m4_include([lib-fontconfig.m4]) + m4_include([lib-tests.m4]) ################################################################################ @@ -93,14 +95,17 @@ AC_DEFUN_ONCE([LIB_DETERMINE_DEPENDENCIES], AC_DEFUN_ONCE([LIB_SETUP_LIBRARIES], [ LIB_SETUP_STD_LIBS - LIB_SETUP_X11 + + LIB_SETUP_ALSA + LIB_SETUP_BUNDLED_LIBS LIB_SETUP_CUPS LIB_SETUP_FONTCONFIG LIB_SETUP_FREETYPE - LIB_SETUP_ALSA + LIB_SETUP_HSDIS LIB_SETUP_LIBFFI - LIB_SETUP_BUNDLED_LIBS LIB_SETUP_MISC_LIBS + LIB_SETUP_X11 + LIB_TESTS_SETUP_GTEST BASIC_JDKLIB_LIBS="" diff --git a/make/autoconf/spec.gmk.in b/make/autoconf/spec.gmk.in index 3dce730970e7d180a3889b8f37e0c56907356b73..5671d4a9f3e5aa1a485ca38f6232598e29e61363 100644 --- a/make/autoconf/spec.gmk.in +++ b/make/autoconf/spec.gmk.in @@ -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 @@ -130,6 +130,13 @@ RELEASE_FILE_LIBC:=@RELEASE_FILE_LIBC@ SOURCE_DATE := @SOURCE_DATE@ ENABLE_REPRODUCIBLE_BUILD := @ENABLE_REPRODUCIBLE_BUILD@ +ISO_8601_FORMAT_STRING := @ISO_8601_FORMAT_STRING@ + +ifneq ($(SOURCE_DATE), updated) + # For "updated" source date value, these are set in InitSupport.gmk + export SOURCE_DATE_EPOCH := $(SOURCE_DATE) + SOURCE_DATE_ISO_8601 := @SOURCE_DATE_ISO_8601@ +endif LIBM:=@LIBM@ LIBDL:=@LIBDL@ @@ -360,7 +367,9 @@ ENABLE_COMPATIBLE_CDS_ALIGNMENT := @ENABLE_COMPATIBLE_CDS_ALIGNMENT@ ALLOW_ABSOLUTE_PATHS_IN_OUTPUT := @ALLOW_ABSOLUTE_PATHS_IN_OUTPUT@ HSDIS_BACKEND := @HSDIS_BACKEND@ +ENABLE_HSDIS_BUNDLING := @ENABLE_HSDIS_BUNDLING@ HSDIS_CFLAGS := @HSDIS_CFLAGS@ +HSDIS_LDFLAGS := @HSDIS_LDFLAGS@ HSDIS_LIBS := @HSDIS_LIBS@ # The boot jdk to use. This is overridden in bootcycle-spec.gmk. Make sure to keep @@ -406,6 +415,7 @@ LIBFFI_CFLAGS:=@LIBFFI_CFLAGS@ ENABLE_LIBFFI_BUNDLING:=@ENABLE_LIBFFI_BUNDLING@ LIBFFI_LIB_FILE:=@LIBFFI_LIB_FILE@ FILE_MACRO_CFLAGS := @FILE_MACRO_CFLAGS@ +BRANCH_PROTECTION_CFLAGS := @BRANCH_PROTECTION_CFLAGS@ STATIC_LIBS_CFLAGS := @STATIC_LIBS_CFLAGS@ @@ -581,7 +591,6 @@ AR := @AR@ ARFLAGS:=@ARFLAGS@ NM:=@NM@ -GNM:=@GNM@ STRIP:=@STRIP@ OBJDUMP:=@OBJDUMP@ CXXFILT:=@CXXFILT@ diff --git a/make/autoconf/toolchain.m4 b/make/autoconf/toolchain.m4 index 5280520b78bf18dad743c1d03e70deb4c7d52b9a..b79d161331d273c5bd456c004ad39ea79cc5f5a6 100644 --- a/make/autoconf/toolchain.m4 +++ b/make/autoconf/toolchain.m4 @@ -39,7 +39,7 @@ VALID_TOOLCHAINS_all="gcc clang xlc microsoft" # These toolchains are valid on different platforms VALID_TOOLCHAINS_linux="gcc clang" -VALID_TOOLCHAINS_macosx="gcc clang" +VALID_TOOLCHAINS_macosx="clang" VALID_TOOLCHAINS_aix="xlc" VALID_TOOLCHAINS_windows="microsoft" @@ -772,8 +772,6 @@ AC_DEFUN_ONCE([TOOLCHAIN_DETECT_TOOLCHAIN_EXTRA], else UTIL_LOOKUP_TOOLCHAIN_PROGS(NM, nm) fi - GNM="$NM" - AC_SUBST(GNM) fi # objcopy is used for moving debug symbols to separate files when @@ -903,8 +901,8 @@ AC_DEFUN_ONCE([TOOLCHAIN_SETUP_BUILD_COMPILERS], BUILD_LDCXX="$BUILD_LD" else if test "x$OPENJDK_BUILD_OS" = xmacosx; then - UTIL_REQUIRE_PROGS(BUILD_CC, clang cc gcc) - UTIL_REQUIRE_PROGS(BUILD_CXX, clang++ CC g++) + UTIL_REQUIRE_PROGS(BUILD_CC, clang) + UTIL_REQUIRE_PROGS(BUILD_CXX, clang++) else UTIL_REQUIRE_PROGS(BUILD_CC, cc gcc) UTIL_REQUIRE_PROGS(BUILD_CXX, CC g++) diff --git a/make/autoconf/toolchain_microsoft.m4 b/make/autoconf/toolchain_microsoft.m4 index 2e02c531da7818f41327803802b0891fec8cf02c..03d4ae50dfb0165d49e28289a4f62b46658ba484 100644 --- a/make/autoconf/toolchain_microsoft.m4 +++ b/make/autoconf/toolchain_microsoft.m4 @@ -481,6 +481,7 @@ AC_DEFUN([TOOLCHAIN_CHECK_POSSIBLE_MSVC_DLL], AC_DEFUN([TOOLCHAIN_SETUP_MSVC_DLL], [ DLL_NAME="$1" + DLL_HELP="$2" MSVC_DLL= if test "x$OPENJDK_TARGET_CPU" = xx86; then @@ -565,7 +566,7 @@ AC_DEFUN([TOOLCHAIN_SETUP_MSVC_DLL], if test "x$MSVC_DLL" = x; then AC_MSG_CHECKING([for $DLL_NAME]) AC_MSG_RESULT([no]) - AC_MSG_ERROR([Could not find $DLL_NAME. Please specify using --with-msvcr-dll.]) + AC_MSG_ERROR([Could not find $DLL_NAME. Please specify using ${DLL_HELP}.]) fi ]) @@ -588,7 +589,7 @@ AC_DEFUN([TOOLCHAIN_SETUP_VS_RUNTIME_DLLS], fi MSVCR_DLL="$MSVC_DLL" else - TOOLCHAIN_SETUP_MSVC_DLL([${MSVCR_NAME}]) + TOOLCHAIN_SETUP_MSVC_DLL([${MSVCR_NAME}], [--with-msvcr-dll]) MSVCR_DLL="$MSVC_DLL" fi AC_SUBST(MSVCR_DLL) @@ -611,7 +612,7 @@ AC_DEFUN([TOOLCHAIN_SETUP_VS_RUNTIME_DLLS], fi MSVCP_DLL="$MSVC_DLL" else - TOOLCHAIN_SETUP_MSVC_DLL([${MSVCP_NAME}]) + TOOLCHAIN_SETUP_MSVC_DLL([${MSVCP_NAME}], [--with-msvcp-dll]) MSVCP_DLL="$MSVC_DLL" fi AC_SUBST(MSVCP_DLL) @@ -636,7 +637,7 @@ AC_DEFUN([TOOLCHAIN_SETUP_VS_RUNTIME_DLLS], fi VCRUNTIME_1_DLL="$MSVC_DLL" else - TOOLCHAIN_SETUP_MSVC_DLL([${VCRUNTIME_1_NAME}]) + TOOLCHAIN_SETUP_MSVC_DLL([${VCRUNTIME_1_NAME}], [--with-vcruntime-1-dll]) VCRUNTIME_1_DLL="$MSVC_DLL" fi fi diff --git a/make/autoconf/util.m4 b/make/autoconf/util.m4 index 877165ab3a364e62a5157856ccf554869084fbb7..15f41abafda9b492c112836b28e304c683e55c32 100644 --- a/make/autoconf/util.m4 +++ b/make/autoconf/util.m4 @@ -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 @@ -230,8 +230,6 @@ AC_DEFUN([UTIL_GET_MATCHING_VALUES], # Converts an ISO-8601 date/time string to a unix epoch timestamp. If no # suitable conversion method was found, an empty string is returned. # -# Sets the specified variable to the resulting list. -# # $1: result variable name # $2: input date/time string AC_DEFUN([UTIL_GET_EPOCH_TIMESTAMP], @@ -241,11 +239,11 @@ AC_DEFUN([UTIL_GET_EPOCH_TIMESTAMP], timestamp=$($DATE --utc --date=$2 +"%s" 2> /dev/null) else # BSD date - timestamp=$($DATE -u -j -f "%F %T" "$2" "+%s" 2> /dev/null) + timestamp=$($DATE -u -j -f "%FZ %TZ" "$2" "+%s" 2> /dev/null) if test "x$timestamp" = x; then - # Perhaps the time was missing - timestamp=$($DATE -u -j -f "%F %T" "$2 00:00:00" "+%s" 2> /dev/null) - # If this did not work, we give up and return the empty string + # BSD date cannot handle trailing milliseconds. + # Try again ignoring characters at end + timestamp=$($DATE -u -j -f "%Y-%m-%dT%H:%M:%S" "$2" "+%s" 2> /dev/null) fi fi $1=$timestamp diff --git a/make/common/JarArchive.gmk b/make/common/JarArchive.gmk index 5a87e4714288ff3dc570bb9747b3af45b29023e3..26b08fc1509017fd18f138bbc8468a46f308c305 100644 --- a/make/common/JarArchive.gmk +++ b/make/common/JarArchive.gmk @@ -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 @@ -193,7 +193,8 @@ define SetupJarArchiveBody $1_UPDATE_CONTENTS=\ if [ "`$(WC) -l $$($1_BIN)/_the.$$($1_JARNAME)_contents | $(AWK) '{ print $$$$1 }'`" -gt "0" ]; then \ $(ECHO) " updating" `$(WC) -l $$($1_BIN)/_the.$$($1_JARNAME)_contents | $(AWK) '{ print $$$$1 }'` files && \ - $$($1_JAR_CMD) --update $$($1_JAR_OPTIONS) --file $$@ @$$($1_BIN)/_the.$$($1_JARNAME)_contents; \ + $(SORT) $$($1_BIN)/_the.$$($1_JARNAME)_contents > $$($1_BIN)/_the.$$($1_JARNAME)_contents_sorted && \ + $$($1_JAR_CMD) --update $$($1_JAR_OPTIONS) --file $$@ @$$($1_BIN)/_the.$$($1_JARNAME)_contents_sorted; \ fi $$(NEWLINE) # The s-variants of the above macros are used when the jar is created from scratch. # NOTICE: please leave the parentheses space separated otherwise the AIX build will break! @@ -212,7 +213,9 @@ define SetupJarArchiveBody | $(SED) 's|$$(src)/|-C $$(src) |g' >> \ $$($1_BIN)/_the.$$($1_JARNAME)_contents) $$(NEWLINE) ) endif - $1_SUPDATE_CONTENTS=$$($1_JAR_CMD) --update $$($1_JAR_OPTIONS) --file $$@ @$$($1_BIN)/_the.$$($1_JARNAME)_contents $$(NEWLINE) + $1_SUPDATE_CONTENTS=\ + $(SORT) $$($1_BIN)/_the.$$($1_JARNAME)_contents > $$($1_BIN)/_the.$$($1_JARNAME)_contents_sorted && \ + $$($1_JAR_CMD) --update $$($1_JAR_OPTIONS) --file $$@ @$$($1_BIN)/_the.$$($1_JARNAME)_contents_sorted $$(NEWLINE) # Use a slightly shorter name for logging, but with enough path to identify this jar. $1_NAME:=$$(subst $$(OUTPUTDIR)/,,$$($1_JAR)) diff --git a/make/common/modules/LauncherCommon.gmk b/make/common/modules/LauncherCommon.gmk index 7ad0375e2e38ff31419eb47d028a652c2dead647..85056bbe40f0c076ba7d2c9738b1c7a0be776a85 100644 --- a/make/common/modules/LauncherCommon.gmk +++ b/make/common/modules/LauncherCommon.gmk @@ -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 @@ -33,13 +33,14 @@ include ToolsJdk.gmk # On Mac, we have always exported all symbols, probably due to oversight # and/or misunderstanding. To emulate this, don't hide any symbols # by default. -# On AIX/xlc we need at least xlc 13.1 for the symbol hiding (see JDK-8214063) # Also provide an override for non-conformant libraries. ifeq ($(TOOLCHAIN_TYPE), gcc) LAUNCHER_CFLAGS += -fvisibility=hidden LDFLAGS_JDKEXE += -Wl,--exclude-libs,ALL else ifeq ($(TOOLCHAIN_TYPE), clang) LAUNCHER_CFLAGS += -fvisibility=hidden +else ifeq ($(TOOLCHAIN_TYPE), xlc) + LAUNCHER_CFLAGS += -qvisibility=hidden endif LAUNCHER_SRC := $(TOPDIR)/src/java.base/share/native/launcher diff --git a/make/common/modules/LibCommon.gmk b/make/common/modules/LibCommon.gmk index 8ca3ddfffe9a606186ad0103fb4928330a390085..aa5c9f0a5c6b87415f853d88915335e5e9ad314a 100644 --- a/make/common/modules/LibCommon.gmk +++ b/make/common/modules/LibCommon.gmk @@ -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,6 @@ WIN_JAVA_LIB := $(SUPPORT_OUTPUTDIR)/native/java.base/libjava/java.lib # On Mac, we have always exported all symbols, probably due to oversight # and/or misunderstanding. To emulate this, don't hide any symbols # by default. -# On AIX/xlc we need at least xlc 13.1 for the symbol hiding (see JDK-8214063) # Also provide an override for non-conformant libraries. ifeq ($(TOOLCHAIN_TYPE), gcc) CFLAGS_JDKLIB += -fvisibility=hidden @@ -47,6 +46,10 @@ 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/jib-profiles.js b/make/conf/jib-profiles.js index e0041e9185130fb591ae6577c61ae9fe2bc9cc47..f16d7fd12e717f31831a949c7f3aafc2f3b6f0a2 100644 --- a/make/conf/jib-profiles.js +++ b/make/conf/jib-profiles.js @@ -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 @@ -258,7 +258,6 @@ var getJibProfilesCommon = function (input, data) { common.release_profile_base = { configure_args: [ "--enable-reproducible-build", - "--with-source-date=current", ], }; // Extra settings for debug profiles @@ -1053,10 +1052,10 @@ var getJibProfilesProfiles = function (input, common, data) { var getJibProfilesDependencies = function (input, common) { var devkit_platform_revisions = { - linux_x64: "gcc10.3.0-OL6.4+1.0", + linux_x64: "gcc11.2.0-OL6.4+1.0", macosx: "Xcode12.4+1.0", windows_x64: "VS2019-16.9.3+1.0", - linux_aarch64: "gcc10.3.0-OL7.6+1.0", + linux_aarch64: "gcc11.2.0-OL7.6+1.0", linux_arm: "gcc8.2.0-Fedora27+1.0", linux_ppc64le: "gcc8.2.0-Fedora27+1.0", linux_s390x: "gcc8.2.0-Fedora27+1.0" @@ -1424,7 +1423,10 @@ var getVersion = function (feature, interim, update, patch, extra1, extra2, extr * other version inputs */ var versionArgs = function(input, common) { - var args = ["--with-version-build=" + common.build_number]; + var args = []; + if (common.build_number != 0) { + args = concat(args, "--with-version-build=" + common.build_number); + } if (input.build_type == "promoted") { args = concat(args, "--with-version-pre=" + version_numbers.get("DEFAULT_PROMOTED_VERSION_PRE"), @@ -1444,6 +1446,14 @@ var versionArgs = function(input, common) { } else { args = concat(args, "--with-version-opt=" + common.build_id); } + var sourceDate + if (input.build_id_data && input.build_id_data.creationTime) { + sourceDate = Math.floor(Date.parse(input.build_id_data.creationTime)/1000); + } else { + sourceDate = "current"; + } + args = concat(args, "--with-source-date=" + sourceDate); + return args; } diff --git a/make/data/publicsuffixlist/VERSION b/make/data/publicsuffixlist/VERSION deleted file mode 100644 index 3367b24a0be6ffa9c2c00af11c65423987ebb9a0..0000000000000000000000000000000000000000 --- a/make/data/publicsuffixlist/VERSION +++ /dev/null @@ -1,2 +0,0 @@ -Github: https://raw.githubusercontent.com/publicsuffix/list/cbbba1d234670453df9c930dfbf510c0474d4301/public_suffix_list.dat -Date: 2020-04-24 diff --git a/make/devkit/Tools.gmk b/make/devkit/Tools.gmk index 19eccf89be2ac185f32d6dd7432671e22f80206a..e94a74d0063e1a254f7e92d8be720bcc7b0a5d92 100644 --- a/make/devkit/Tools.gmk +++ b/make/devkit/Tools.gmk @@ -87,8 +87,17 @@ endif # Define external dependencies # Latest that could be made to work. -GCC_VER := 10.3.0 -ifeq ($(GCC_VER), 10.3.0) +GCC_VER := 11.2.0 +ifeq ($(GCC_VER), 11.2.0) + gcc_ver := gcc-11.2.0 + binutils_ver := binutils-2.37 + ccache_ver := ccache-3.7.12 + mpfr_ver := mpfr-4.1.0 + gmp_ver := gmp-6.2.1 + mpc_ver := mpc-1.2.1 + gdb_ver := gdb-11.1 + REQUIRED_MIN_MAKE_MAJOR_VERSION := 4 +else ifeq ($(GCC_VER), 10.3.0) gcc_ver := gcc-10.3.0 binutils_ver := binutils-2.36.1 ccache_ver := ccache-3.7.11 diff --git a/make/hotspot/lib/CompileGtest.gmk b/make/hotspot/lib/CompileGtest.gmk index cb2bbccc1686aa4a28a8f8557523eee75d0b80ca..f16b9a747bcc435320386cf394b0e183a8bac6d2 100644 --- a/make/hotspot/lib/CompileGtest.gmk +++ b/make/hotspot/lib/CompileGtest.gmk @@ -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 @@ -49,7 +49,7 @@ $(eval $(call SetupJdkLibrary, BUILD_GTEST_LIBGTEST, \ $(GTEST_FRAMEWORK_SRC)/googletest/src \ $(GTEST_FRAMEWORK_SRC)/googlemock/src, \ INCLUDE_FILES := gtest-all.cc gmock-all.cc, \ - DISABLED_WARNINGS_gcc := undef unused-result format-nonliteral, \ + DISABLED_WARNINGS_gcc := undef unused-result format-nonliteral maybe-uninitialized, \ DISABLED_WARNINGS_clang := undef unused-result format-nonliteral, \ CFLAGS := $(JVM_CFLAGS) \ -I$(GTEST_FRAMEWORK_SRC)/googletest \ diff --git a/make/jdk/src/classes/build/tools/generatecharacter/CharacterScript.java b/make/jdk/src/classes/build/tools/generatecharacter/CharacterScript.java index fda7a561e87f92f2ecb58b1ca625dbda618dfcc0..d242cb8ed42912d8bf01680a28db13b7a53562fb 100644 --- a/make/jdk/src/classes/build/tools/generatecharacter/CharacterScript.java +++ b/make/jdk/src/classes/build/tools/generatecharacter/CharacterScript.java @@ -115,7 +115,7 @@ public class CharacterScript { for (j = 0; j < scriptSize; j++) { for (int cp = scripts[j][0]; cp <= scripts[j][1]; cp++) { - String name = names[scripts[j][2]].toUpperCase(Locale.ENGLISH);; + String name = names[scripts[j][2]].toUpperCase(Locale.ENGLISH); if (cp > 0xffff) System.out.printf("%05X %s%n", cp, name); else diff --git a/make/langtools/src/classes/build/tools/symbolgenerator/CreateSymbols.java b/make/langtools/src/classes/build/tools/symbolgenerator/CreateSymbols.java index ea700f0b660c6558c21e1dfd91d195d4eaaf0988..41f600a817e0df7102fa856228814ba20689935a 100644 --- a/make/langtools/src/classes/build/tools/symbolgenerator/CreateSymbols.java +++ b/make/langtools/src/classes/build/tools/symbolgenerator/CreateSymbols.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, 2021, 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 @@ -156,7 +156,7 @@ import java.util.Optional; * A tool for processing the .sym.txt files. * * To add historical data for JDK N, N >= 11, do the following: - * * cd /make/data/symbols + * * cd /src/jdk.compiler/share/data/symbols * * /bin/java --add-exports jdk.jdeps/com.sun.tools.classfile=ALL-UNNAMED \ * --add-exports jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED \ * --add-exports jdk.compiler/com.sun.tools.javac.jvm=ALL-UNNAMED \ @@ -164,7 +164,7 @@ import java.util.Optional; * --add-modules jdk.jdeps \ * ../../../make/langtools/src/classes/build/tools/symbolgenerator/CreateSymbols.java \ * build-description-incremental symbols include.list - * * sanity-check the new and updates files in make/data/symbols and commit them + * * sanity-check the new and updates files in src/jdk.compiler/share/data/symbols and commit them * * The tools allows to: * * convert the .sym.txt into class/sig files for ct.sym @@ -212,7 +212,8 @@ import java.util.Optional; * To generate the .sym.txt files for OpenJDK 7 and 8: * /bin/java build.tools.symbolgenerator.Probe OpenJDK7.classes * /bin/java build.tools.symbolgenerator.Probe OpenJDK8.classes - * java build.tools.symbolgenerator.CreateSymbols build-description make/data/symbols $TOPDIR make/data/symbols/include.list + * java build.tools.symbolgenerator.CreateSymbols build-description src/jdk.compiler/share/data/symbols + * $TOPDIR src/jdk.compiler/share/data/symbols/include.list * 8 OpenJDK8.classes '' * 7 OpenJDK7.classes 8 * diff --git a/make/langtools/tools/genstubs/GenStubs.java b/make/langtools/tools/genstubs/GenStubs.java index 9f8fc7a7a596132f2d8dc77246141ce62d10729a..bcf73fc5f71c89795b9b112ea72a5abdbd40c84f 100644 --- a/make/langtools/tools/genstubs/GenStubs.java +++ b/make/langtools/tools/genstubs/GenStubs.java @@ -213,7 +213,7 @@ public class GenStubs { long prevClassMods = currClassMods; currClassMods = tree.mods.flags; try { - super.visitClassDef(tree);; + super.visitClassDef(tree); } finally { currClassMods = prevClassMods; } diff --git a/make/modules/java.base/Copy.gmk b/make/modules/java.base/Copy.gmk index d61a274317296b60c32e75458a9b921a8a78ef34..16d1b8d910cfe521a266bc23c9215c0cf2aca38f 100644 --- a/make/modules/java.base/Copy.gmk +++ b/make/modules/java.base/Copy.gmk @@ -246,6 +246,23 @@ ifeq ($(ENABLE_LIBFFI_BUNDLING), true) TARGETS += $(COPY_LIBFFI) endif +################################################################################ +# Optionally copy hsdis into the the image + +ifeq ($(ENABLE_HSDIS_BUNDLING), true) + HSDIS_NAME := hsdis-$(OPENJDK_TARGET_CPU_LEGACY_LIB)$(SHARED_LIBRARY_SUFFIX) + HSDIS_PATH := $(SUPPORT_OUTPUTDIR)/hsdis/$(HSDIS_NAME) + + $(eval $(call SetupCopyFiles, COPY_HSDIS, \ + FILES := $(HSDIS_PATH), \ + DEST := $(call FindLibDirForModule, $(MODULE)), \ + FLATTEN := true, \ + MACRO := install-file-nolink, \ + )) + + TARGETS += $(COPY_HSDIS) +endif + ################################################################################ # Generate classfile_constants.h diff --git a/make/modules/java.base/Gendata.gmk b/make/modules/java.base/Gendata.gmk index 4b894eeae4a6634b14f1491b323d03998856a77a..9e5cfe2d0fc40e10ff9c66e8e225ea154102a008 100644 --- a/make/modules/java.base/Gendata.gmk +++ b/make/modules/java.base/Gendata.gmk @@ -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 @@ -39,7 +39,7 @@ include gendata/GendataPublicSuffixList.gmk GENDATA_UNINAME := $(JDK_OUTPUTDIR)/modules/java.base/java/lang/uniName.dat -$(GENDATA_UNINAME): $(TOPDIR)/make/data/unicodedata/UnicodeData.txt $(BUILD_TOOLS_JDK) +$(GENDATA_UNINAME): $(MODULE_SRC)/share/data/unicodedata/UnicodeData.txt $(BUILD_TOOLS_JDK) $(call MakeDir, $(@D)) $(TOOL_CHARACTERNAME) $< $@ @@ -49,7 +49,7 @@ TARGETS += $(GENDATA_UNINAME) GENDATA_CURDATA := $(JDK_OUTPUTDIR)/modules/java.base/java/util/currency.data -$(GENDATA_CURDATA): $(TOPDIR)/make/data/currency/CurrencyData.properties $(BUILD_TOOLS_JDK) +$(GENDATA_CURDATA): $(MODULE_SRC)/share/data/currency/CurrencyData.properties $(BUILD_TOOLS_JDK) $(call MakeDir, $(@D)) $(RM) $@ $(TOOL_GENERATECURRENCYDATA) -o $@.tmp -i $< @@ -63,7 +63,7 @@ TARGETS += $(GENDATA_CURDATA) ifneq ($(CACERTS_SRC), ) GENDATA_CACERTS_SRC := $(CACERTS_SRC) else - GENDATA_CACERTS_SRC := $(TOPDIR)/make/data/cacerts/ + GENDATA_CACERTS_SRC := $(MODULE_SRC)/share/data/cacerts/ endif GENDATA_CACERTS := $(SUPPORT_OUTPUTDIR)/modules_libs/java.base/security/cacerts @@ -78,7 +78,7 @@ endif ################################################################################ -GENDATA_JAVA_SECURITY_SRC := $(TOPDIR)/src/java.base/share/conf/security/java.security +GENDATA_JAVA_SECURITY_SRC := $(MODULE_SRC)/share/conf/security/java.security GENDATA_JAVA_SECURITY := $(SUPPORT_OUTPUTDIR)/modules_conf/java.base/security/java.security ifeq ($(UNLIMITED_CRYPTO), true) diff --git a/make/modules/java.base/Gensrc.gmk b/make/modules/java.base/Gensrc.gmk index 9ea2d015d3bec2901cd6ca94a6ba77b629dc0158..9c9576bdd4a3290acc5518cd09a6e3abe0b00535 100644 --- a/make/modules/java.base/Gensrc.gmk +++ b/make/modules/java.base/Gensrc.gmk @@ -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 @@ -46,8 +46,8 @@ TARGETS += $(GENSRC_BASELOCALEDATA) CLDR_DATA_DIR := $(TOPDIR)/make/data/cldr/common GENSRC_DIR := $(SUPPORT_OUTPUTDIR)/gensrc/java.base CLDR_GEN_DONE := $(GENSRC_DIR)/_cldr-gensrc.marker -TZ_DATA_DIR := $(TOPDIR)/make/data/tzdata -ZONENAME_TEMPLATE := $(TOPDIR)/src/java.base/share/classes/java/time/format/ZoneName.java.template +TZ_DATA_DIR := $(MODULE_SRC)/share/data/tzdata +ZONENAME_TEMPLATE := $(MODULE_SRC)/share/classes/java/time/format/ZoneName.java.template $(CLDR_GEN_DONE): $(wildcard $(CLDR_DATA_DIR)/dtd/*.dtd) \ $(wildcard $(CLDR_DATA_DIR)/main/en*.xml) \ @@ -74,12 +74,12 @@ TARGETS += $(CLDR_GEN_DONE) include GensrcProperties.gmk $(eval $(call SetupCompileProperties, LIST_RESOURCE_BUNDLE, \ - SRC_DIRS := $(TOPDIR)/src/java.base/share/classes/sun/launcher/resources, \ + SRC_DIRS := $(MODULE_SRC)/share/classes/sun/launcher/resources, \ CLASS := ListResourceBundle, \ )) $(eval $(call SetupCompileProperties, SUN_UTIL, \ - SRC_DIRS := $(TOPDIR)/src/java.base/share/classes/sun/util/resources, \ + SRC_DIRS := $(MODULE_SRC)/share/classes/sun/util/resources, \ CLASS := sun.util.resources.LocaleNamesBundle, \ )) @@ -98,7 +98,7 @@ TARGETS += $(COPY_ZH_HK) GENSRC_LSREQUIVMAPS := $(SUPPORT_OUTPUTDIR)/gensrc/java.base/sun/util/locale/LocaleEquivalentMaps.java -$(GENSRC_LSREQUIVMAPS): $(TOPDIR)/make/data/lsrdata/language-subtag-registry.txt $(BUILD_TOOLS_JDK) +$(GENSRC_LSREQUIVMAPS): $(MODULE_SRC)/share/data/lsrdata/language-subtag-registry.txt $(BUILD_TOOLS_JDK) $(call MakeDir, $(@D)) $(TOOL_GENERATELSREQUIVMAPS) $< $@ $(COPYRIGHT_YEAR) diff --git a/make/modules/java.base/gendata/GendataBlockedCerts.gmk b/make/modules/java.base/gendata/GendataBlockedCerts.gmk index 65f75012a33d5648b3e6a3d1a7cc3b6612a3964d..b6149b457cd5093b9fcd1b73d9bedc2478d3f25c 100644 --- a/make/modules/java.base/gendata/GendataBlockedCerts.gmk +++ b/make/modules/java.base/gendata/GendataBlockedCerts.gmk @@ -1,5 +1,5 @@ # -# Copyright (c) 2014, 2021, 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 @@ -23,7 +23,7 @@ # questions. # -GENDATA_BLOCKED_CERTS_SRC += $(TOPDIR)/make/data/blockedcertsconverter/blocked.certs.pem +GENDATA_BLOCKED_CERTS_SRC += $(MODULE_SRC)/share/data/blockedcertsconverter/blocked.certs.pem GENDATA_BLOCKED_CERTS := $(SUPPORT_OUTPUTDIR)/modules_libs/$(MODULE)/security/blocked.certs $(GENDATA_BLOCKED_CERTS): $(BUILD_TOOLS_JDK) $(GENDATA_BLOCKED_CERTS_SRC) diff --git a/make/modules/java.base/gendata/GendataBreakIterator.gmk b/make/modules/java.base/gendata/GendataBreakIterator.gmk index d314253b4fe31bc1e3d849e53176375858e90f49..857ce2b7c34fc94fc82be091de65d211bb385740 100644 --- a/make/modules/java.base/gendata/GendataBreakIterator.gmk +++ b/make/modules/java.base/gendata/GendataBreakIterator.gmk @@ -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 @@ -74,7 +74,7 @@ BREAK_ITERATOR_BOOTCLASSPATH := \ # Generate data resource files. # input -UNICODEDATA := $(TOPDIR)/make/data/unicodedata/UnicodeData.txt +UNICODEDATA := $(MODULE_SRC)/share/data/unicodedata/UnicodeData.txt # output BASE_DATA_PKG_DIR := $(JDK_OUTPUTDIR)/modules/java.base/sun/text/resources diff --git a/make/modules/java.base/gendata/GendataPublicSuffixList.gmk b/make/modules/java.base/gendata/GendataPublicSuffixList.gmk index 757098a619fc2c89d9c4dedc6219cb7f838dbd2f..189fccf0c0da535a2ceebfbe036f1331b7d0f0df 100644 --- a/make/modules/java.base/gendata/GendataPublicSuffixList.gmk +++ b/make/modules/java.base/gendata/GendataPublicSuffixList.gmk @@ -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 @@ -25,7 +25,7 @@ include $(SPEC) -GENDATA_PUBLICSUFFIXLIST_SRC += $(TOPDIR)/make/data/publicsuffixlist/public_suffix_list.dat +GENDATA_PUBLICSUFFIXLIST_SRC += $(MODULE_SRC)/share/data/publicsuffixlist/public_suffix_list.dat GENDATA_PUBLICSUFFIXLIST := $(SUPPORT_OUTPUTDIR)/modules_libs/$(MODULE)/security/public_suffix_list.dat $(GENDATA_PUBLICSUFFIXLIST): $(GENDATA_PUBLICSUFFIXLIST_SRC) $(BUILD_TOOLS_JDK) diff --git a/make/modules/java.base/gendata/GendataTZDB.gmk b/make/modules/java.base/gendata/GendataTZDB.gmk index 1352178694fe357c96bc4b9fa525560534ec3e54..593ed8a8f115879016afae95621de59080b0d705 100644 --- a/make/modules/java.base/gendata/GendataTZDB.gmk +++ b/make/modules/java.base/gendata/GendataTZDB.gmk @@ -1,5 +1,5 @@ # -# Copyright (c) 2012, 2018, 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 @@ -28,7 +28,7 @@ GENDATA_TZDB := # # Time zone data file creation # -TZDATA_DIR := $(TOPDIR)/make/data/tzdata +TZDATA_DIR := $(MODULE_SRC)/share/data/tzdata TZDATA_TZFILE := africa antarctica asia australasia europe northamerica southamerica backward etcetera gmt jdk11_backward TZDATA_TZFILES := $(addprefix $(TZDATA_DIR)/,$(TZDATA_TZFILE)) diff --git a/make/modules/java.base/gensrc/GensrcBuffer.gmk b/make/modules/java.base/gensrc/GensrcBuffer.gmk index 6ad432fb86678b4bc14bcc8fab711e47b2d23939..ce22230a8e18444ccd597555c71c4a3225f44f75 100644 --- a/make/modules/java.base/gensrc/GensrcBuffer.gmk +++ b/make/modules/java.base/gensrc/GensrcBuffer.gmk @@ -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 @@ -27,7 +27,7 @@ GENSRC_BUFFER := GENSRC_BUFFER_DST := $(SUPPORT_OUTPUTDIR)/gensrc/java.base/java/nio -GENSRC_BUFFER_SRC := $(TOPDIR)/src/java.base/share/classes/java/nio +GENSRC_BUFFER_SRC := $(MODULE_SRC)/share/classes/java/nio ### diff --git a/make/modules/java.base/gensrc/GensrcCharacterData.gmk b/make/modules/java.base/gensrc/GensrcCharacterData.gmk index eb9380165061cc750cb54d5faaffd3f34cc5052f..115a28309a2374a70e8ed4147dd259f27357e65d 100644 --- a/make/modules/java.base/gensrc/GensrcCharacterData.gmk +++ b/make/modules/java.base/gensrc/GensrcCharacterData.gmk @@ -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 @@ -29,8 +29,8 @@ GENSRC_CHARACTERDATA := -CHARACTERDATA = $(TOPDIR)/make/data/characterdata -UNICODEDATA = $(TOPDIR)/make/data/unicodedata +CHARACTERDATA_TEMPLATES = $(MODULE_SRC)/share/classes/java/lang +UNICODEDATA = $(MODULE_SRC)/share/data/unicodedata ifneq ($(DEBUG_LEVEL), release) ifeq ($(ALLOW_ABSOLUTE_PATHS_IN_OUTPUT), true) @@ -40,11 +40,11 @@ endif define SetupCharacterData $(SUPPORT_OUTPUTDIR)/gensrc/java.base/java/lang/$1.java: \ - $(CHARACTERDATA)/$1.java.template + $(CHARACTERDATA_TEMPLATES)/$1.java.template $$(call LogInfo, Generating $1.java) $$(call MakeDir, $$(@D)) $(TOOL_GENERATECHARACTER) $2 $(DEBUG_OPTION) \ - -template $(CHARACTERDATA)/$1.java.template \ + -template $(CHARACTERDATA_TEMPLATES)/$1.java.template \ -spec $(UNICODEDATA)/UnicodeData.txt \ -specialcasing $(UNICODEDATA)/SpecialCasing.txt \ -proplist $(UNICODEDATA)/PropList.txt \ diff --git a/make/modules/java.base/gensrc/GensrcCharsetCoder.gmk b/make/modules/java.base/gensrc/GensrcCharsetCoder.gmk index 79fa54b19cc0072af4840be05fbaae9b11257e18..2940ba4231931a797d68972fdd92daeda42c9993 100644 --- a/make/modules/java.base/gensrc/GensrcCharsetCoder.gmk +++ b/make/modules/java.base/gensrc/GensrcCharsetCoder.gmk @@ -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 @@ -27,7 +27,7 @@ GENSRC_CHARSETCODER := GENSRC_CHARSETCODER_DST := $(SUPPORT_OUTPUTDIR)/gensrc/java.base/java/nio/charset -GENSRC_CHARSETCODER_SRC := $(TOPDIR)/src/java.base/share/classes/java/nio +GENSRC_CHARSETCODER_SRC := $(MODULE_SRC)/share/classes/java/nio GENSRC_CHARSETCODER_TEMPLATE := $(GENSRC_CHARSETCODER_SRC)/charset/Charset-X-Coder.java.template diff --git a/make/modules/java.base/gensrc/GensrcEmojiData.gmk b/make/modules/java.base/gensrc/GensrcEmojiData.gmk index d92cb9354a3fd3e4f6f0606df9d07728b144f27d..1af03bcafe92523c6fbd9d08953ccd247d1ebead 100644 --- a/make/modules/java.base/gensrc/GensrcEmojiData.gmk +++ b/make/modules/java.base/gensrc/GensrcEmojiData.gmk @@ -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 @@ -29,8 +29,8 @@ GENSRC_EMOJIDATA := $(SUPPORT_OUTPUTDIR)/gensrc/java.base/java/util/regex/EmojiData.java -EMOJIDATATEMP = $(TOPDIR)/src/java.base/share/classes/java/util/regex/EmojiData.java.template -UNICODEDATA = $(TOPDIR)/make/data/unicodedata +EMOJIDATATEMP = $(MODULE_SRC)/share/classes/java/util/regex/EmojiData.java.template +UNICODEDATA = $(MODULE_SRC)/share/data/unicodedata $(GENSRC_EMOJIDATA): $(BUILD_TOOLS_JDK) $(EMOJIDATATEMP) $(UNICODEDATA)/emoji/emoji-data.txt $(call LogInfo, Generating $@) diff --git a/make/modules/java.base/gensrc/GensrcExceptions.gmk b/make/modules/java.base/gensrc/GensrcExceptions.gmk index 37fed896560b7217e2c45e9a4da5598244d3959c..1c4974b4a28c6f01ad8f9d8713895b99f9e43682 100644 --- a/make/modules/java.base/gensrc/GensrcExceptions.gmk +++ b/make/modules/java.base/gensrc/GensrcExceptions.gmk @@ -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 @@ -27,7 +27,7 @@ GENSRC_EXCEPTIONS := GENSRC_EXCEPTIONS_DST := $(SUPPORT_OUTPUTDIR)/gensrc/java.base/java/nio -GENSRC_EXCEPTIONS_SRC := $(TOPDIR)/src/java.base/share/classes/java/nio +GENSRC_EXCEPTIONS_SRC := $(MODULE_SRC)/share/classes/java/nio GENSRC_EXCEPTIONS_CMD := $(TOPDIR)/make/scripts/genExceptions.sh GENSRC_EXCEPTIONS_SRC_DIRS := . charset channels diff --git a/make/modules/java.base/gensrc/GensrcLocaleData.gmk b/make/modules/java.base/gensrc/GensrcLocaleData.gmk index 1e28d91ab684eb9941da504b0915e997b7f69800..c04bab5317570eb830f44316a61ac6cdd1c58ae7 100644 --- a/make/modules/java.base/gensrc/GensrcLocaleData.gmk +++ b/make/modules/java.base/gensrc/GensrcLocaleData.gmk @@ -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 @@ -29,8 +29,8 @@ # First go look for all locale files LOCALE_FILES := $(call FindFiles, \ - $(TOPDIR)/src/$(MODULE)/share/classes/sun/text/resources \ - $(TOPDIR)/src/$(MODULE)/share/classes/sun/util/resources, \ + $(MODULE_SRC)/share/classes/sun/text/resources \ + $(MODULE_SRC)/share/classes/sun/util/resources, \ FormatData_*.java FormatData_*.properties \ CollationData_*.java CollationData_*.properties \ TimeZoneNames_*.java TimeZoneNames_*.properties \ diff --git a/make/modules/java.base/gensrc/GensrcScopedMemoryAccess.gmk b/make/modules/java.base/gensrc/GensrcScopedMemoryAccess.gmk index b431acc14e1183e577b15200cb393d04d6d9cc13..54fea77571e90209b635811a9348c5732c900d25 100644 --- a/make/modules/java.base/gensrc/GensrcScopedMemoryAccess.gmk +++ b/make/modules/java.base/gensrc/GensrcScopedMemoryAccess.gmk @@ -24,7 +24,7 @@ # SCOPED_MEMORY_ACCESS_GENSRC_DIR := $(SUPPORT_OUTPUTDIR)/gensrc/java.base/jdk/internal/misc -SCOPED_MEMORY_ACCESS_SRC_DIR := $(TOPDIR)/src/java.base/share/classes/jdk/internal/misc +SCOPED_MEMORY_ACCESS_SRC_DIR := $(MODULE_SRC)/share/classes/jdk/internal/misc SCOPED_MEMORY_ACCESS_TEMPLATE := $(SCOPED_MEMORY_ACCESS_SRC_DIR)/X-ScopedMemoryAccess.java.template SCOPED_MEMORY_ACCESS_BIN_TEMPLATE := $(SCOPED_MEMORY_ACCESS_SRC_DIR)/X-ScopedMemoryAccess-bin.java.template SCOPED_MEMORY_ACCESS_DEST := $(SCOPED_MEMORY_ACCESS_GENSRC_DIR)/ScopedMemoryAccess.java @@ -139,7 +139,7 @@ endef SCOPE_MEMORY_ACCESS_TYPES := Byte Short Char Int Long Float Double $(foreach t, $(SCOPE_MEMORY_ACCESS_TYPES), \ $(eval $(call GenerateScopedOp,BIN_$t,$t))) - + $(SCOPED_MEMORY_ACCESS_DEST): $(BUILD_TOOLS_JDK) $(SCOPED_MEMORY_ACCESS_TEMPLATE) $(SCOPED_MEMORY_ACCESS_BIN_TEMPLATE) $(call MakeDir, $(SCOPED_MEMORY_ACCESS_GENSRC_DIR)) $(CAT) $(SCOPED_MEMORY_ACCESS_TEMPLATE) > $(SCOPED_MEMORY_ACCESS_DEST) @@ -147,5 +147,5 @@ $(SCOPED_MEMORY_ACCESS_DEST): $(BUILD_TOOLS_JDK) $(SCOPED_MEMORY_ACCESS_TEMPLATE $(TOOL_SPP) -nel -K$(BIN_$t_type) -Dtype=$(BIN_$t_type) -DType=$(BIN_$t_Type) $(BIN_$t_ARGS) \ -i$(SCOPED_MEMORY_ACCESS_BIN_TEMPLATE) -o$(SCOPED_MEMORY_ACCESS_DEST) ;) $(PRINTF) "}\n" >> $(SCOPED_MEMORY_ACCESS_DEST) - + TARGETS += $(SCOPED_MEMORY_ACCESS_DEST) diff --git a/make/modules/java.base/gensrc/GensrcVarHandles.gmk b/make/modules/java.base/gensrc/GensrcVarHandles.gmk index 579488379c333d853223de5c5a949d30dc55f3b2..e1686834bf5e908dd8d64676c23408ede400b9a1 100644 --- a/make/modules/java.base/gensrc/GensrcVarHandles.gmk +++ b/make/modules/java.base/gensrc/GensrcVarHandles.gmk @@ -1,5 +1,5 @@ # -# Copyright (c) 2015, 2020, 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 @@ -26,7 +26,7 @@ GENSRC_VARHANDLES := VARHANDLES_GENSRC_DIR := $(SUPPORT_OUTPUTDIR)/gensrc/java.base/java/lang/invoke -VARHANDLES_SRC_DIR := $(TOPDIR)/src/java.base/share/classes/java/lang/invoke +VARHANDLES_SRC_DIR := $(MODULE_SRC)/share/classes/java/lang/invoke ################################################################################ # Setup a rule for generating a VarHandle java class diff --git a/make/modules/java.desktop/gendata/GendataFontConfig.gmk b/make/modules/java.desktop/gendata/GendataFontConfig.gmk index 42e3f4b485f14c3c6ca126825fc9748ecf5a32bc..92a64b986e189c4c6a6c98a841607989814a0769 100644 --- a/make/modules/java.desktop/gendata/GendataFontConfig.gmk +++ b/make/modules/java.desktop/gendata/GendataFontConfig.gmk @@ -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 @@ -23,30 +23,35 @@ # questions. # -GENDATA_FONT_CONFIG_DST := $(SUPPORT_OUTPUTDIR)/modules_libs/$(MODULE) +FONTCONFIG_DATA_DIR := $(MODULE_SRC)/$(OPENJDK_TARGET_OS)/data/fontconfig +FONTCONFIG_SRC_FILE := $(FONTCONFIG_DATA_DIR)/fontconfig.properties -GENDATA_FONT_CONFIG_DATA_DIR ?= $(TOPDIR)/make/data/fontconfig +FONTCONFIG_DEST_DIR := $(SUPPORT_OUTPUTDIR)/modules_libs/$(MODULE) +FONTCONFIG_OUT_FILE := $(FONTCONFIG_DEST_DIR)/fontconfig.properties.src +FONTCONFIG_OUT_BIN_FILE := $(FONTCONFIG_DEST_DIR)/fontconfig.bfc -GENDATA_FONT_CONFIG_SRC_FILES := \ - $(wildcard $(GENDATA_FONT_CONFIG_DATA_DIR)/$(OPENJDK_TARGET_OS).*) +ifneq ($(findstring $(LOG_LEVEL), debug trace), ) + FONTCONFIG_VERBOSE_FLAG := -verbose +endif +# Not all OSes have a fontconfig file +ifneq ($(wildcard $(FONTCONFIG_SRC_FILE)), ) -$(GENDATA_FONT_CONFIG_DST)/%.src: \ - $(GENDATA_FONT_CONFIG_DATA_DIR)/$(OPENJDK_TARGET_OS).% + # Copy properties file as-is + $(FONTCONFIG_OUT_FILE): $(FONTCONFIG_SRC_FILE) + $(call LogInfo, Copying fontconfig.properties) $(call install-file) -$(GENDATA_FONT_CONFIG_DST)/%.bfc: \ - $(GENDATA_FONT_CONFIG_DATA_DIR)/$(OPENJDK_TARGET_OS).%.properties \ - $(BUILD_TOOLS_JDK) + TARGETS += $(FONTCONFIG_OUT_FILE) + + # Generate binary representation + $(FONTCONFIG_OUT_BIN_FILE): $(FONTCONFIG_SRC_FILE) $(BUILD_TOOLS_JDK) + $(call LogInfo, Compiling fontconfig.properties to binary) $(call MakeTargetDir) $(RM) $@ - $(TOOL_COMPILEFONTCONFIG) $< $@ + $(TOOL_COMPILEFONTCONFIG) $(FONTCONFIG_VERBOSE_FLAG) $< $@ $(CHMOD) 444 $@ + TARGETS += $(FONTCONFIG_OUT_BIN_FILE) -GENDATA_FONT_CONFIGS := $(patsubst $(GENDATA_FONT_CONFIG_DATA_DIR)/$(OPENJDK_TARGET_OS).%, \ - $(GENDATA_FONT_CONFIG_DST)/%.src, $(GENDATA_FONT_CONFIG_SRC_FILES)) -GENDATA_BFONT_CONFIGS := $(patsubst $(GENDATA_FONT_CONFIG_DATA_DIR)/$(OPENJDK_TARGET_OS).%.properties, \ - $(GENDATA_FONT_CONFIG_DST)/%.bfc, $(GENDATA_FONT_CONFIG_SRC_FILES)) - -TARGETS := $(GENDATA_FONT_CONFIGS) $(GENDATA_BFONT_CONFIGS) +endif diff --git a/make/modules/java.desktop/gensrc/GensrcIcons.gmk b/make/modules/java.desktop/gensrc/GensrcIcons.gmk index e0a6c107eccfe2dc1b1f7bafe64431e7b117590f..28434d3f4c1be48a8f541e01fabb472c20164a54 100644 --- a/make/modules/java.desktop/gensrc/GensrcIcons.gmk +++ b/make/modules/java.desktop/gensrc/GensrcIcons.gmk @@ -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 @@ -29,7 +29,7 @@ GENSRC_AWT_ICONS_TMP := $(SUPPORT_OUTPUTDIR)/gensrc/java.desktop GENSRC_AWT_ICONS_DST := $(GENSRC_AWT_ICONS_TMP)/sun/awt/ # Allow this to be overridden from a custom makefile -X11_ICONS_PATH_PREFIX ?= $(TOPDIR)/src/java.desktop/$(OPENJDK_TARGET_OS_TYPE) +X11_ICONS_PATH_PREFIX ?= $(MODULE_SRC)/$(OPENJDK_TARGET_OS_TYPE) GENSRC_AWT_ICONS_SRC += \ $(X11_ICONS_PATH_PREFIX)/classes/sun/awt/X11/java-icon16.png \ @@ -38,7 +38,7 @@ GENSRC_AWT_ICONS_SRC += \ $(X11_ICONS_PATH_PREFIX)/classes/sun/awt/X11/java-icon48.png -AWT_ICONPATH := $(TOPDIR)/src/java.desktop/share/classes/sun/awt/resources +AWT_ICONPATH := $(MODULE_SRC)/share/classes/sun/awt/resources GENSRC_AWT_ICONS_SRC += \ $(AWT_ICONPATH)/security-icon-bw16.png \ @@ -111,7 +111,7 @@ ifeq ($(call isTargetOs, macosx), true) GENSRC_OSX_ICONS_DST := $(SUPPORT_OUTPUTDIR)/headers/java.desktop GENSRC_OSX_ICONS := $(GENSRC_OSX_ICONS_DST)/AWTIconData.h - GENSRC_OSX_ICONS_SRC ?= $(TOPDIR)/make/data/macosxicons/JavaApp.icns + GENSRC_OSX_ICONS_SRC ?= $(MODULE_SRC)/macosx/data/macosxicons/JavaApp.icns $(GENSRC_OSX_ICONS): $(GENSRC_OSX_ICONS_SRC) $(BUILD_TOOLS_JDK) diff --git a/make/modules/java.desktop/gensrc/GensrcSwing.gmk b/make/modules/java.desktop/gensrc/GensrcSwing.gmk index cfb50831d1bcc7d7464bb3ec2f31a702c85a16db..abd428f3641987eb687ab7d46d87402663c34228 100644 --- a/make/modules/java.desktop/gensrc/GensrcSwing.gmk +++ b/make/modules/java.desktop/gensrc/GensrcSwing.gmk @@ -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 @@ -28,7 +28,7 @@ # NIMBUS_PACKAGE = javax.swing.plaf NIMBUS_GENSRC_DIR = $(SUPPORT_OUTPUTDIR)/gensrc/java.desktop/javax/swing/plaf/nimbus -NIMBUS_SKIN_FILE = $(TOPDIR)/src/java.desktop/share/classes/javax/swing/plaf/nimbus/skin.laf +NIMBUS_SKIN_FILE = $(MODULE_SRC)/share/classes/javax/swing/plaf/nimbus/skin.laf $(SUPPORT_OUTPUTDIR)/gensrc/java.desktop/_the.generated_nimbus: $(NIMBUS_SKIN_FILE) $(BUILD_TOOLS_JDK) $(call LogInfo, Generating Nimbus source files) diff --git a/make/modules/java.desktop/gensrc/GensrcX11Wrappers.gmk b/make/modules/java.desktop/gensrc/GensrcX11Wrappers.gmk index d46328f8607984f61186a67bce64e0c89ae41ea1..25402ad035a5b6d0f4729bf360c30f62bc04f58a 100644 --- a/make/modules/java.desktop/gensrc/GensrcX11Wrappers.gmk +++ b/make/modules/java.desktop/gensrc/GensrcX11Wrappers.gmk @@ -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 @@ -24,13 +24,13 @@ # # Generate java sources using the X11 offsets that are precalculated in files -# make/data/x11wrappergen/sizes-
    .txt. +# src/java.desktop/unix/data/x11wrappergen/sizes-
    .txt. # Put the generated Java classes used to interface X11 from awt here. GENSRC_X11WRAPPERS_OUTPUTDIR := $(SUPPORT_OUTPUTDIR)/gensrc/java.desktop/sun/awt/X11 # The pre-calculated offset file are stored here: -GENSRC_X11WRAPPERS_DATADIR := $(TOPDIR)/make/data/x11wrappergen +GENSRC_X11WRAPPERS_DATADIR := $(MODULE_SRC)/unix/data/x11wrappergen GENSRC_X11WRAPPERS_DATA := $(GENSRC_X11WRAPPERS_DATADIR)/sizes-$(OPENJDK_TARGET_CPU_BITS).txt # Run the tool on the offset files to generate several Java classes used in awt. diff --git a/make/modules/java.desktop/lib/Awt2dLibraries.gmk b/make/modules/java.desktop/lib/Awt2dLibraries.gmk index a0c4082554626e942d200e73373a734eb99f8e3e..3cf8ca8a820e8439ab1582b3d2d01a1ea69442b9 100644 --- a/make/modules/java.desktop/lib/Awt2dLibraries.gmk +++ b/make/modules/java.desktop/lib/Awt2dLibraries.gmk @@ -742,7 +742,7 @@ ifeq ($(ENABLE_HEADLESS_ONLY), false) maybe-uninitialized shift-negative-value implicit-fallthrough \ unused-function, \ DISABLED_WARNINGS_clang := incompatible-pointer-types sign-compare \ - deprecated-declarations, \ + deprecated-declarations null-pointer-subtraction, \ DISABLED_WARNINGS_microsoft := 4018 4244 4267, \ LDFLAGS := $(LDFLAGS_JDKLIB) \ $(call SET_SHARED_LIBRARY_ORIGIN), \ diff --git a/make/modules/jdk.charsets/Gensrc.gmk b/make/modules/jdk.charsets/Gensrc.gmk index ca9c19409411ee21d325c89ac588567ea2b2a690..1fac37b2c4b99fa1268cc96241b4f7dc6fb5ee2c 100644 --- a/make/modules/jdk.charsets/Gensrc.gmk +++ b/make/modules/jdk.charsets/Gensrc.gmk @@ -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 @@ -38,8 +38,8 @@ CHARSET_TEMPLATES := \ $(CHARSET_DATA_DIR)/SingleByte-X.java.template \ $(CHARSET_DATA_DIR)/DoubleByte-X.java.template CHARSET_EXTENDED_JAVA_TEMPLATES := \ - $(TOPDIR)/src/jdk.charsets/share/classes/sun/nio/cs/ext/ExtendedCharsets.java.template -CHARSET_EXTENDED_JAVA_DIR := $(TOPDIR)/src/jdk.charsets/share/classes/sun/nio/cs/ext + $(MODULE_SRC)/share/classes/sun/nio/cs/ext/ExtendedCharsets.java.template +CHARSET_EXTENDED_JAVA_DIR := $(MODULE_SRC)/share/classes/sun/nio/cs/ext CHARSET_STANDARD_OS := stdcs-$(OPENJDK_TARGET_OS) $(CHARSET_DONE_CS)-extcs: $(CHARSET_DATA_DIR)/charsets \ diff --git a/make/modules/jdk.compiler/Gendata.gmk b/make/modules/jdk.compiler/Gendata.gmk index 85815e5524b1edeb7423a5199a328fa053e70c49..5471fa1127c1c664aeac5613fc4f3a65a2c83e80 100644 --- a/make/modules/jdk.compiler/Gendata.gmk +++ b/make/modules/jdk.compiler/Gendata.gmk @@ -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 @@ -41,7 +41,7 @@ CT_MODULES := $(DOCS_MODULES) # Get the complete module source path: CT_MODULESOURCEPATH := $(call GetModuleSrcPath) -CT_DATA_DESCRIPTION += $(TOPDIR)/make/data/symbols/symbols +CT_DATA_DESCRIPTION += $(MODULE_SRC)/share/data/symbols/symbols COMPILECREATESYMBOLS_ADD_EXPORTS := \ --add-exports java.base/jdk.internal.javac=java.compiler.interim,jdk.compiler.interim \ @@ -65,7 +65,7 @@ $(eval $(call SetupJavaCompilation, COMPILE_CREATE_SYMBOLS, \ $(SUPPORT_OUTPUTDIR)/symbols/ct.sym: \ $(COMPILE_CREATE_SYMBOLS) \ - $(wildcard $(TOPDIR)/make/data/symbols/*) \ + $(wildcard $(MODULE_SRC)/share/data/symbols/*) \ $(MODULE_INFOS) $(RM) -r $(@D) $(MKDIR) -p $(@D) diff --git a/make/modules/jdk.javadoc/Gendata.gmk b/make/modules/jdk.javadoc/Gendata.gmk index 50ef87545a4cdf360d52e3de65973777dac21bab..69c93c29468b890b3888f25c65fd75e3a6277fa7 100644 --- a/make/modules/jdk.javadoc/Gendata.gmk +++ b/make/modules/jdk.javadoc/Gendata.gmk @@ -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 @@ -39,7 +39,7 @@ JAVADOC_MODULES := $(DOCS_MODULES) # Get the complete module source path: JAVADOC_MODULESOURCEPATH := $(call GetModuleSrcPath) -CT_DATA_DESCRIPTION += $(TOPDIR)/make/data/symbols/symbols +CT_DATA_DESCRIPTION += $(TOPDIR)/src/jdk.compiler/share/data/symbols/symbols COMPILECREATESYMBOLS_ADD_EXPORTS := \ --add-exports java.base/jdk.internal=java.compiler.interim,jdk.compiler.interim \ @@ -68,7 +68,7 @@ ELEMENT_LISTS_DIR := $(JDK_JAVADOC_DIR)/$(ELEMENT_LISTS_PKG) $(JDK_JAVADOC_DIR)/_element_lists.marker: \ $(COMPILE_CREATE_SYMBOLS) \ - $(wildcard $(TOPDIR)/make/data/symbols/*) \ + $(wildcard $(TOPDIR)/src/jdk.compiler/share/data/symbols/*) \ $(MODULE_INFOS) $(call MakeTargetDir) $(call LogInfo, Creating javadoc element lists) diff --git a/make/modules/jdk.jdi/Gensrc.gmk b/make/modules/jdk.jdi/Gensrc.gmk index 5487e950921ea59c36051566daa702791c9174c7..7db06b5c95873a3e0b5258124b82dcc095286bff 100644 --- a/make/modules/jdk.jdi/Gensrc.gmk +++ b/make/modules/jdk.jdi/Gensrc.gmk @@ -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 @@ -26,10 +26,11 @@ include GensrcCommonJdk.gmk ################################################################################ -# Translate the Java debugger wire protocol (jdwp.spec) file into a JDWP.java file -# and a JDWPCommands.h C-header file. +# Translate the Java debugger wire protocol (jdwp.spec) file into a front-end +# Java implementation (JDWP.java), a back-end C header file (JDWPCommands.h) and +# an HTML documentation file (jdwp-protocol.html). -JDWP_SPEC_FILE := $(TOPDIR)/make/data/jdwp/jdwp.spec +JDWP_SPEC_FILE := $(TOPDIR)/src/java.se/share/data/jdwp/jdwp.spec HEADER_FILE := $(SUPPORT_OUTPUTDIR)/headers/jdk.jdwp.agent/JDWPCommands.h JAVA_FILE := $(SUPPORT_OUTPUTDIR)/gensrc/jdk.jdi/com/sun/tools/jdi/JDWP.java HTML_FILE := $(SUPPORT_OUTPUTDIR)/gensrc/jdk.jdi/jdwp-protocol.html diff --git a/make/modules/jdk.localedata/Gensrc.gmk b/make/modules/jdk.localedata/Gensrc.gmk index 09f014e8607c6c6244cae52a91f16f2c9fa37fcf..233572c8a544bde9338cd01146636658dd0b6bb6 100644 --- a/make/modules/jdk.localedata/Gensrc.gmk +++ b/make/modules/jdk.localedata/Gensrc.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 @@ -57,7 +57,7 @@ TARGETS += $(CLDR_GEN_DONE) include GensrcProperties.gmk $(eval $(call SetupCompileProperties, COMPILE_PROPERTIES, \ - SRC_DIRS := $(TOPDIR)/src/jdk.localedata/share/classes/sun/util/resources, \ + SRC_DIRS := $(MODULE_SRC)/share/classes/sun/util/resources, \ CLASS := sun.util.resources.LocaleNamesBundle, \ KEEP_ALL_TRANSLATIONS := true, \ )) diff --git a/make/scripts/compare.sh b/make/scripts/compare.sh index cc05476c997e5090c860882fe72e241b1bf89531..a0006fa4ceee104ccc9948cf7bd3a27a45993615 100644 --- a/make/scripts/compare.sh +++ b/make/scripts/compare.sh @@ -1,6 +1,6 @@ #!/bin/bash # -# 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 @@ -324,7 +324,7 @@ compare_general_files() { ! -name "*.cpl" ! -name "*.pdb" ! -name "*.exp" ! -name "*.ilk" \ ! -name "*.lib" ! -name "*.jmod" ! -name "*.exe" \ ! -name "*.obj" ! -name "*.o" ! -name "jspawnhelper" ! -name "*.a" \ - ! -name "*.tar.gz" ! -name "*.jsa" ! -name "gtestLauncher" \ + ! -name "*.tar.gz" ! -name "classes_nocoops.jsa" ! -name "gtestLauncher" \ ! -name "*.map" \ | $GREP -v "./bin/" | $SORT | $FILTER) diff --git a/make/scripts/generate-symbol-data.sh b/make/scripts/generate-symbol-data.sh index 56aa8016dd6a8a55730682e0484eb034a1cb51fa..ee1d540715fd3905021269dcc6c4ae48cc57e1d8 100644 --- a/make/scripts/generate-symbol-data.sh +++ b/make/scripts/generate-symbol-data.sh @@ -34,19 +34,19 @@ # - have a checkout the JDK to which the data should be added (or in which the data should be updated). # The checkout directory will be denoted as "${JDK_CHECKOUT}" in the further text. # The checkout must not have any local changes that could interfere with the new data. In particular, -# there must be absolutely no changed, new or removed files under the ${JDK_CHECKOUT}/make/data/symbols +# there must be absolutely no changed, new or removed files under the ${JDK_CHECKOUT}/src/jdk.compiler/share/data/symbols # directory. # - open a terminal program and run these commands: -# cd "${JDK_CHECKOUT}"/make/data/symbols +# cd "${JDK_CHECKOUT}"/src/jdk.compiler/share/data/symbols # bash ../../scripts/generate-symbol-data.sh "${JDK_N_INSTALL}" -# - this command will generate or update data for "--release N" into the ${JDK_CHECKOUT}/make/data/symbols +# - this command will generate or update data for "--release N" into the ${JDK_CHECKOUT}/src/jdk.compiler/share/data/symbols # directory, updating all registration necessary. If the goal was to update the data, and there are no -# new or changed files in the ${JDK_CHECKOUT}/make/data/symbols directory after running this script, +# new or changed files in the ${JDK_CHECKOUT}/src/jdk.compiler/share/data/symbols directory after running this script, # there were no relevant changes and no further action is necessary. Note that version for N > 9 are encoded # using capital letters, i.e. A represents version 10, B represents 11, and so on. The version numbers are in -# the names of the files in the ${JDK_CHECKOUT}/make/data/symbols directory, as well as in -# the ${JDK_CHECKOUT}/make/data/symbols/symbols file. -# - if there are any changed/new files in the ${JDK_CHECKOUT}/make/data/symbols directory after running this script, +# the names of the files in the ${JDK_CHECKOUT}/src/jdk.compiler/share/data/symbols directory, as well as in +# the ${JDK_CHECKOUT}/src/jdk.compiler/share/data/symbols/symbols file. +# - if there are any changed/new files in the ${JDK_CHECKOUT}/src/jdk.compiler/share/data/symbols directory after running this script, # then all the changes in this directory, including any new files, need to be sent for review and eventually pushed. # The commit message should specify which binary build was installed in the ${JDK_N_INSTALL} directory and also # include the SCM state that was used to build it, which can be found in ${JDK_N_INSTALL}/release, @@ -59,12 +59,12 @@ if [ "$1x" = "x" ] ; then fi; if [ ! -f symbols ] ; then - echo "Must run inside the make/data/symbols directory" >&2 + echo "Must run inside the src/jdk.compiler/share/data/symbols directory" >&2 exit 1 fi; if [ "`git status --porcelain=v1 .`x" != "x" ] ; then - echo "The make/data/symbols directory contains local changes!" >&2 + echo "The src/jdk.compiler/share/data/symbols directory contains local changes!" >&2 exit 1 fi; diff --git a/make/test/JtregNativeJdk.gmk b/make/test/JtregNativeJdk.gmk index 6797952bc05d3e8facec0eaeb98f344527d984c0..89cc94f90bf02e9b4eb8bd8fc1700253fd2115fb 100644 --- a/make/test/JtregNativeJdk.gmk +++ b/make/test/JtregNativeJdk.gmk @@ -64,6 +64,7 @@ ifeq ($(call isTargetOs, windows), true) BUILD_JDK_JTREG_EXECUTABLES_LIBS_exeCallerAccessTest := jvm.lib BUILD_JDK_JTREG_EXECUTABLES_LIBS_exeNullCallerClassLoaderTest := jvm.lib BUILD_JDK_JTREG_EXECUTABLES_LIBS_exeNullCallerLookupTest := jvm.lib + BUILD_JDK_JTREG_EXECUTABLES_LIBS_exeNullCallerResourceBundle := jvm.lib BUILD_JDK_JTREG_EXECUTABLES_LIBS_exerevokeall := advapi32.lib BUILD_JDK_JTREG_LIBRARIES_CFLAGS_libAsyncStackWalk := /EHsc BUILD_JDK_JTREG_LIBRARIES_CFLAGS_libAsyncInvokers := /EHsc @@ -84,6 +85,7 @@ else BUILD_JDK_JTREG_EXECUTABLES_LIBS_exeCallerAccessTest := -ljvm BUILD_JDK_JTREG_EXECUTABLES_LIBS_exeNullCallerClassLoaderTest := -ljvm BUILD_JDK_JTREG_EXECUTABLES_LIBS_exeNullCallerLookupTest := -ljvm + BUILD_JDK_JTREG_EXECUTABLES_LIBS_exeNullCallerResourceBundle := -ljvm endif ifeq ($(call isTargetOs, macosx), true) diff --git a/src/hotspot/cpu/aarch64/aarch64.ad b/src/hotspot/cpu/aarch64/aarch64.ad index 5b4ad50b2a5d22ddb9401050a8236a76141c1794..68fd336aa33b6f6ce3c685279ae5cd8e110bc777 100644 --- a/src/hotspot/cpu/aarch64/aarch64.ad +++ b/src/hotspot/cpu/aarch64/aarch64.ad @@ -1311,6 +1311,9 @@ public: // predicate controlling translation of CompareAndSwapX bool needs_acquiring_load_exclusive(const Node *load); + // Assert that the given node is not a variable shift. + bool assert_not_var_shift(const Node* n); + // predicate controlling addressing modes bool size_fits_all_mem_uses(AddPNode* addp, int shift); %} @@ -1725,6 +1728,12 @@ bool needs_acquiring_load_exclusive(const Node *n) return true; } +// Assert that the given node is not a variable shift. +bool assert_not_var_shift(const Node* n) { + assert(!n->as_ShiftV()->is_var_shift(), "illegal variable shift"); + return true; +} + #define __ _masm. // advance declarations for helper functions to convert register @@ -1853,6 +1862,10 @@ void MachPrologNode::format(PhaseRegAlloc *ra_, outputStream *st) const { if (C->output()->need_stack_bang(framesize)) st->print("# stack bang size=%d\n\t", framesize); + if (VM_Version::use_rop_protection()) { + st->print("ldr zr, [lr]\n\t"); + st->print("pacia lr, rfp\n\t"); + } if (framesize < ((1 << 9) + 2 * wordSize)) { st->print("sub sp, sp, #%d\n\t", framesize); st->print("stp rfp, lr, [sp, #%d]", framesize - 2 * wordSize); @@ -1961,6 +1974,10 @@ void MachEpilogNode::format(PhaseRegAlloc *ra_, outputStream *st) const { st->print("add sp, sp, rscratch1\n\t"); st->print("ldp lr, rfp, [sp],#%d\n\t", (2 * wordSize)); } + if (VM_Version::use_rop_protection()) { + st->print("autia lr, rfp\n\t"); + st->print("ldr zr, [lr]\n\t"); + } if (do_polling() && C->is_method_compilation()) { st->print("# test polling word\n\t"); @@ -3201,16 +3218,30 @@ encode %{ rscratch1, stlrb); %} + enc_class aarch64_enc_stlrb0(memory mem) %{ + MOV_VOLATILE(zr, $mem$$base, $mem$$index, $mem$$scale, $mem$$disp, + rscratch1, stlrb); + %} + enc_class aarch64_enc_stlrh(iRegI src, memory mem) %{ MOV_VOLATILE(as_Register($src$$reg), $mem$$base, $mem$$index, $mem$$scale, $mem$$disp, rscratch1, stlrh); %} + enc_class aarch64_enc_stlrh0(memory mem) %{ + MOV_VOLATILE(zr, $mem$$base, $mem$$index, $mem$$scale, $mem$$disp, + rscratch1, stlrh); + %} + enc_class aarch64_enc_stlrw(iRegI src, memory mem) %{ MOV_VOLATILE(as_Register($src$$reg), $mem$$base, $mem$$index, $mem$$scale, $mem$$disp, rscratch1, stlrw); %} + enc_class aarch64_enc_stlrw0(memory mem) %{ + MOV_VOLATILE(zr, $mem$$base, $mem$$index, $mem$$scale, $mem$$disp, + rscratch1, stlrw); + %} enc_class aarch64_enc_ldarsbw(iRegI dst, memory mem) %{ Register dst_reg = as_Register($dst$$reg); @@ -3301,6 +3332,11 @@ encode %{ rscratch1, stlr); %} + enc_class aarch64_enc_stlr0(memory mem) %{ + MOV_VOLATILE(zr, $mem$$base, $mem$$index, $mem$$scale, $mem$$disp, + rscratch1, stlr); + %} + enc_class aarch64_enc_fstlrs(vRegF src, memory mem) %{ { C2_MacroAssembler _masm(&cbuf); @@ -8275,6 +8311,18 @@ instruct storeB_volatile(iRegIorL2I src, /* sync_memory*/indirect mem) ins_pipe(pipe_class_memory); %} +instruct storeimmB0_volatile(immI0 zero, /* sync_memory*/indirect mem) +%{ + match(Set mem (StoreB mem zero)); + + ins_cost(VOLATILE_REF_COST); + format %{ "stlrb zr, $mem\t# byte" %} + + ins_encode(aarch64_enc_stlrb0(mem)); + + ins_pipe(pipe_class_memory); +%} + // Store Char/Short instruct storeC_volatile(iRegIorL2I src, /* sync_memory*/indirect mem) %{ @@ -8288,6 +8336,18 @@ instruct storeC_volatile(iRegIorL2I src, /* sync_memory*/indirect mem) ins_pipe(pipe_class_memory); %} +instruct storeimmC0_volatile(immI0 zero, /* sync_memory*/indirect mem) +%{ + match(Set mem (StoreC mem zero)); + + ins_cost(VOLATILE_REF_COST); + format %{ "stlrh zr, $mem\t# short" %} + + ins_encode(aarch64_enc_stlrh0(mem)); + + ins_pipe(pipe_class_memory); +%} + // Store Integer instruct storeI_volatile(iRegIorL2I src, /* sync_memory*/indirect mem) @@ -8302,6 +8362,18 @@ instruct storeI_volatile(iRegIorL2I src, /* sync_memory*/indirect mem) ins_pipe(pipe_class_memory); %} +instruct storeimmI0_volatile(immI0 zero, /* sync_memory*/indirect mem) +%{ + match(Set mem(StoreI mem zero)); + + ins_cost(VOLATILE_REF_COST); + format %{ "stlrw zr, $mem\t# int" %} + + ins_encode(aarch64_enc_stlrw0(mem)); + + ins_pipe(pipe_class_memory); +%} + // Store Long (64 bit signed) instruct storeL_volatile(iRegL src, /* sync_memory*/indirect mem) %{ @@ -8315,6 +8387,18 @@ instruct storeL_volatile(iRegL src, /* sync_memory*/indirect mem) ins_pipe(pipe_class_memory); %} +instruct storeimmL0_volatile(immL0 zero, /* sync_memory*/indirect mem) +%{ + match(Set mem (StoreL mem zero)); + + ins_cost(VOLATILE_REF_COST); + format %{ "stlr zr, $mem\t# int" %} + + ins_encode(aarch64_enc_stlr0(mem)); + + ins_pipe(pipe_class_memory); +%} + // Store Pointer instruct storeP_volatile(iRegP src, /* sync_memory*/indirect mem) %{ @@ -8328,6 +8412,18 @@ instruct storeP_volatile(iRegP src, /* sync_memory*/indirect mem) ins_pipe(pipe_class_memory); %} +instruct storeimmP0_volatile(immP0 zero, /* sync_memory*/indirect mem) +%{ + match(Set mem (StoreP mem zero)); + + ins_cost(VOLATILE_REF_COST); + format %{ "stlr zr, $mem\t# ptr" %} + + ins_encode(aarch64_enc_stlr0(mem)); + + ins_pipe(pipe_class_memory); +%} + // Store Compressed Pointer instruct storeN_volatile(iRegN src, /* sync_memory*/indirect mem) %{ @@ -8341,6 +8437,18 @@ instruct storeN_volatile(iRegN src, /* sync_memory*/indirect mem) ins_pipe(pipe_class_memory); %} +instruct storeimmN0_volatile(immN0 zero, /* sync_memory*/indirect mem) +%{ + match(Set mem (StoreN mem zero)); + + ins_cost(VOLATILE_REF_COST); + format %{ "stlrw zr, $mem\t# compressed ptr" %} + + ins_encode(aarch64_enc_stlrw0(mem)); + + ins_pipe(pipe_class_memory); +%} + // Store Float instruct storeF_volatile(vRegF src, /* sync_memory*/indirect mem) %{ @@ -16972,13 +17080,13 @@ instruct array_equalsC(iRegP_R1 ary1, iRegP_R2 ary2, iRegI_R0 result, ins_pipe(pipe_class_memory); %} -instruct has_negatives(iRegP_R1 ary1, iRegI_R2 len, iRegI_R0 result, rFlagsReg cr) +instruct count_positives(iRegP_R1 ary1, iRegI_R2 len, iRegI_R0 result, rFlagsReg cr) %{ - match(Set result (HasNegatives ary1 len)); + match(Set result (CountPositives ary1 len)); effect(USE_KILL ary1, USE_KILL len, KILL cr); - format %{ "has negatives byte[] $ary1,$len -> $result" %} + format %{ "count positives byte[] $ary1,$len -> $result" %} ins_encode %{ - address tpc = __ has_negatives($ary1$$Register, $len$$Register, $result$$Register); + address tpc = __ count_positives($ary1$$Register, $len$$Register, $result$$Register); if (tpc == NULL) { ciEnv::current()->record_failure("CodeCache is full"); return; diff --git a/src/hotspot/cpu/aarch64/aarch64_neon.ad b/src/hotspot/cpu/aarch64/aarch64_neon.ad index 7c84a93583b10a8e9ff5c4526c84970f3e02419f..feecd8ab90add28181a2c7b2bd615432703389b9 100644 --- a/src/hotspot/cpu/aarch64/aarch64_neon.ad +++ b/src/hotspot/cpu/aarch64/aarch64_neon.ad @@ -1,5 +1,5 @@ -// Copyright (c) 2020, 2021, Oracle and/or its affiliates. All rights reserved. -// Copyright (c) 2020, 2021, Arm Limited. All rights reserved. +// Copyright (c) 2020, 2022, Oracle and/or its affiliates. All rights reserved. +// Copyright (c) 2020, 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 @@ -4400,11 +4400,17 @@ instruct vxor16B(vecX dst, vecX src1, vecX src2) // ------------------------------ Shift --------------------------------------- -instruct vshiftcnt8B(vecD dst, iRegIorL2I cnt) %{ +// Vector shift count +// Note-1: Low 8 bits of each element are used, so it doesn't matter if we +// treat it as ints or bytes here. +// Note-2: Shift value is negated for RShiftCntV additionally. See the comments +// on vsra8B rule for more details. + +instruct vslcnt8B(vecD dst, iRegIorL2I cnt) %{ predicate(UseSVE == 0 && (n->as_Vector()->length_in_bytes() == 4 || - n->as_Vector()->length_in_bytes() == 8)); + n->as_Vector()->length_in_bytes() == 8)); match(Set dst (LShiftCntV cnt)); - match(Set dst (RShiftCntV cnt)); + ins_cost(INSN_COST); format %{ "dup $dst, $cnt\t# shift count vector (8B)" %} ins_encode %{ __ dup(as_FloatRegister($dst$$reg), __ T8B, as_Register($cnt$$reg)); @@ -4412,10 +4418,10 @@ instruct vshiftcnt8B(vecD dst, iRegIorL2I cnt) %{ ins_pipe(vdup_reg_reg64); %} -instruct vshiftcnt16B(vecX dst, iRegIorL2I cnt) %{ - predicate(UseSVE == 0 && (n->as_Vector()->length_in_bytes() == 16)); +instruct vslcnt16B(vecX dst, iRegIorL2I cnt) %{ + predicate(UseSVE == 0 && n->as_Vector()->length_in_bytes() == 16); match(Set dst (LShiftCntV cnt)); - match(Set dst (RShiftCntV cnt)); + ins_cost(INSN_COST); format %{ "dup $dst, $cnt\t# shift count vector (16B)" %} ins_encode %{ __ dup(as_FloatRegister($dst$$reg), __ T16B, as_Register($cnt$$reg)); @@ -4423,9 +4429,35 @@ instruct vshiftcnt16B(vecX dst, iRegIorL2I cnt) %{ ins_pipe(vdup_reg_reg128); %} +instruct vsrcnt8B(vecD dst, iRegIorL2I cnt) %{ + predicate(UseSVE == 0 && (n->as_Vector()->length_in_bytes() == 4 || + n->as_Vector()->length_in_bytes() == 8)); + match(Set dst (RShiftCntV cnt)); + ins_cost(INSN_COST * 2); + format %{ "negw rscratch1, $cnt\t" + "dup $dst, rscratch1\t# shift count vector (8B)" %} + ins_encode %{ + __ negw(rscratch1, as_Register($cnt$$reg)); + __ dup(as_FloatRegister($dst$$reg), __ T8B, rscratch1); + %} + ins_pipe(vdup_reg_reg64); +%} + +instruct vsrcnt16B(vecX dst, iRegIorL2I cnt) %{ + predicate(UseSVE == 0 && n->as_Vector()->length_in_bytes() == 16); + match(Set dst (RShiftCntV cnt)); + ins_cost(INSN_COST * 2); + format %{ "negw rscratch1, $cnt\t" + "dup $dst, rscratch1\t# shift count vector (16B)" %} + ins_encode %{ + __ negw(rscratch1, as_Register($cnt$$reg)); + __ dup(as_FloatRegister($dst$$reg), __ T16B, rscratch1); + %} + ins_pipe(vdup_reg_reg128); +%} + instruct vsll8B(vecD dst, vecD src, vecD shift) %{ - predicate(n->as_Vector()->length() == 4 || - n->as_Vector()->length() == 8); + predicate(n->as_Vector()->length() == 4 || n->as_Vector()->length() == 8); match(Set dst (LShiftVB src shift)); ins_cost(INSN_COST); format %{ "sshl $dst,$src,$shift\t# vector (8B)" %} @@ -4459,8 +4491,6 @@ instruct vsll16B(vecX dst, vecX src, vecX shift) %{ // LoadVector RShiftCntV // | / // RShiftVI -// Note: In inner loop, multiple neg instructions are used, which can be -// moved to outer loop and merge into one neg instruction. // // Case 2: The vector shift count is from loading. // This case isn't supported by middle-end now. But it's supported by @@ -4470,83 +4500,145 @@ instruct vsll16B(vecX dst, vecX src, vecX shift) %{ // | / // RShiftVI // +// The negate is conducted in RShiftCntV rule for case 1, whereas it's done in +// RShiftV* rules for case 2. Because there exists an optimization opportunity +// for case 1, that is, multiple neg instructions in inner loop can be hoisted +// to outer loop and merged into one neg instruction. +// +// Note that ShiftVNode::is_var_shift() indicates whether the vector shift +// count is a variable vector(case 2) or not(a vector generated by RShiftCntV, +// i.e. case 1). -instruct vsra8B(vecD dst, vecD src, vecD shift, vecD tmp) %{ - predicate(n->as_Vector()->length() == 4 || - n->as_Vector()->length() == 8); +instruct vsra8B(vecD dst, vecD src, vecD shift) %{ + predicate((n->as_Vector()->length() == 4 || n->as_Vector()->length() == 8) && + !n->as_ShiftV()->is_var_shift()); match(Set dst (RShiftVB src shift)); ins_cost(INSN_COST); - effect(TEMP tmp); - format %{ "negr $tmp,$shift\t" - "sshl $dst,$src,$tmp\t# vector (8B)" %} + format %{ "sshl $dst,$src,$shift\t# vector (8B)" %} + ins_encode %{ + __ sshl(as_FloatRegister($dst$$reg), __ T8B, + as_FloatRegister($src$$reg), + as_FloatRegister($shift$$reg)); + %} + ins_pipe(vshift64); +%} + +instruct vsra8B_var(vecD dst, vecD src, vecD shift) %{ + predicate((n->as_Vector()->length() == 4 || n->as_Vector()->length() == 8) && + n->as_ShiftV()->is_var_shift()); + match(Set dst (RShiftVB src shift)); + ins_cost(INSN_COST * 2); + effect(TEMP_DEF dst); + format %{ "negr $dst,$shift\t" + "sshl $dst,$src,$dst\t# vector (8B)" %} ins_encode %{ - __ negr(as_FloatRegister($tmp$$reg), __ T8B, + __ negr(as_FloatRegister($dst$$reg), __ T8B, as_FloatRegister($shift$$reg)); __ sshl(as_FloatRegister($dst$$reg), __ T8B, as_FloatRegister($src$$reg), - as_FloatRegister($tmp$$reg)); + as_FloatRegister($dst$$reg)); %} ins_pipe(vshift64); %} -instruct vsra16B(vecX dst, vecX src, vecX shift, vecX tmp) %{ - predicate(n->as_Vector()->length() == 16); +instruct vsra16B(vecX dst, vecX src, vecX shift) %{ + predicate(n->as_Vector()->length() == 16 && !n->as_ShiftV()->is_var_shift()); match(Set dst (RShiftVB src shift)); ins_cost(INSN_COST); - effect(TEMP tmp); - format %{ "negr $tmp,$shift\t" - "sshl $dst,$src,$tmp\t# vector (16B)" %} + format %{ "sshl $dst,$src,$shift\t# vector (16B)" %} ins_encode %{ - __ negr(as_FloatRegister($tmp$$reg), __ T16B, + __ sshl(as_FloatRegister($dst$$reg), __ T16B, + as_FloatRegister($src$$reg), + as_FloatRegister($shift$$reg)); + %} + ins_pipe(vshift128); +%} + +instruct vsra16B_var(vecX dst, vecX src, vecX shift) %{ + predicate(n->as_Vector()->length() == 16 && n->as_ShiftV()->is_var_shift()); + match(Set dst (RShiftVB src shift)); + ins_cost(INSN_COST * 2); + effect(TEMP_DEF dst); + format %{ "negr $dst,$shift\t" + "sshl $dst,$src,$dst\t# vector (16B)" %} + ins_encode %{ + __ negr(as_FloatRegister($dst$$reg), __ T16B, as_FloatRegister($shift$$reg)); __ sshl(as_FloatRegister($dst$$reg), __ T16B, as_FloatRegister($src$$reg), - as_FloatRegister($tmp$$reg)); + as_FloatRegister($dst$$reg)); %} ins_pipe(vshift128); %} -instruct vsrl8B(vecD dst, vecD src, vecD shift, vecD tmp) %{ - predicate(n->as_Vector()->length() == 4 || - n->as_Vector()->length() == 8); +instruct vsrl8B(vecD dst, vecD src, vecD shift) %{ + predicate((n->as_Vector()->length() == 4 || n->as_Vector()->length() == 8) && + !n->as_ShiftV()->is_var_shift()); match(Set dst (URShiftVB src shift)); ins_cost(INSN_COST); - effect(TEMP tmp); - format %{ "negr $tmp,$shift\t" - "ushl $dst,$src,$tmp\t# vector (8B)" %} + format %{ "ushl $dst,$src,$shift\t# vector (8B)" %} ins_encode %{ - __ negr(as_FloatRegister($tmp$$reg), __ T8B, + __ ushl(as_FloatRegister($dst$$reg), __ T8B, + as_FloatRegister($src$$reg), + as_FloatRegister($shift$$reg)); + %} + ins_pipe(vshift64); +%} + +instruct vsrl8B_var(vecD dst, vecD src, vecD shift) %{ + predicate((n->as_Vector()->length() == 4 || n->as_Vector()->length() == 8) && + n->as_ShiftV()->is_var_shift()); + match(Set dst (URShiftVB src shift)); + ins_cost(INSN_COST * 2); + effect(TEMP_DEF dst); + format %{ "negr $dst,$shift\t" + "ushl $dst,$src,$dst\t# vector (8B)" %} + ins_encode %{ + __ negr(as_FloatRegister($dst$$reg), __ T8B, as_FloatRegister($shift$$reg)); __ ushl(as_FloatRegister($dst$$reg), __ T8B, as_FloatRegister($src$$reg), - as_FloatRegister($tmp$$reg)); + as_FloatRegister($dst$$reg)); %} ins_pipe(vshift64); %} -instruct vsrl16B(vecX dst, vecX src, vecX shift, vecX tmp) %{ - predicate(n->as_Vector()->length() == 16); +instruct vsrl16B(vecX dst, vecX src, vecX shift) %{ + predicate(n->as_Vector()->length() == 16 && !n->as_ShiftV()->is_var_shift()); match(Set dst (URShiftVB src shift)); ins_cost(INSN_COST); - effect(TEMP tmp); - format %{ "negr $tmp,$shift\t" - "ushl $dst,$src,$tmp\t# vector (16B)" %} + format %{ "ushl $dst,$src,$shift\t# vector (16B)" %} + ins_encode %{ + __ ushl(as_FloatRegister($dst$$reg), __ T16B, + as_FloatRegister($src$$reg), + as_FloatRegister($shift$$reg)); + %} + ins_pipe(vshift128); +%} + +instruct vsrl16B_var(vecX dst, vecX src, vecX shift) %{ + predicate(n->as_Vector()->length() == 16 && n->as_ShiftV()->is_var_shift()); + match(Set dst (URShiftVB src shift)); + ins_cost(INSN_COST * 2); + effect(TEMP_DEF dst); + format %{ "negr $dst,$shift\t" + "ushl $dst,$src,$dst\t# vector (16B)" %} ins_encode %{ - __ negr(as_FloatRegister($tmp$$reg), __ T16B, + __ negr(as_FloatRegister($dst$$reg), __ T16B, as_FloatRegister($shift$$reg)); __ ushl(as_FloatRegister($dst$$reg), __ T16B, as_FloatRegister($src$$reg), - as_FloatRegister($tmp$$reg)); + as_FloatRegister($dst$$reg)); %} ins_pipe(vshift128); %} instruct vsll8B_imm(vecD dst, vecD src, immI shift) %{ - predicate(n->as_Vector()->length() == 4 || - n->as_Vector()->length() == 8); + predicate((n->as_Vector()->length() == 4 || n->as_Vector()->length() == 8) && + assert_not_var_shift(n)); match(Set dst (LShiftVB src (LShiftCntV shift))); ins_cost(INSN_COST); - format %{ "shl $dst, $src, $shift\t# vector (8B)" %} + format %{ "shl $dst, $src, $shift\t# vector (8B)" %} ins_encode %{ int sh = (int)$shift$$constant; if (sh >= 8) { @@ -4562,10 +4654,10 @@ instruct vsll8B_imm(vecD dst, vecD src, immI shift) %{ %} instruct vsll16B_imm(vecX dst, vecX src, immI shift) %{ - predicate(n->as_Vector()->length() == 16); + predicate(n->as_Vector()->length() == 16 && assert_not_var_shift(n)); match(Set dst (LShiftVB src (LShiftCntV shift))); ins_cost(INSN_COST); - format %{ "shl $dst, $src, $shift\t# vector (16B)" %} + format %{ "shl $dst, $src, $shift\t# vector (16B)" %} ins_encode %{ int sh = (int)$shift$$constant; if (sh >= 8) { @@ -4581,40 +4673,40 @@ instruct vsll16B_imm(vecX dst, vecX src, immI shift) %{ %} instruct vsra8B_imm(vecD dst, vecD src, immI shift) %{ - predicate(n->as_Vector()->length() == 4 || - n->as_Vector()->length() == 8); + predicate((n->as_Vector()->length() == 4 || n->as_Vector()->length() == 8) && + assert_not_var_shift(n)); match(Set dst (RShiftVB src (RShiftCntV shift))); ins_cost(INSN_COST); - format %{ "sshr $dst, $src, $shift\t# vector (8B)" %} + format %{ "sshr $dst, $src, $shift\t# vector (8B)" %} ins_encode %{ int sh = (int)$shift$$constant; if (sh >= 8) sh = 7; __ sshr(as_FloatRegister($dst$$reg), __ T8B, - as_FloatRegister($src$$reg), sh); + as_FloatRegister($src$$reg), sh); %} ins_pipe(vshift64_imm); %} instruct vsra16B_imm(vecX dst, vecX src, immI shift) %{ - predicate(n->as_Vector()->length() == 16); + predicate(n->as_Vector()->length() == 16 && assert_not_var_shift(n)); match(Set dst (RShiftVB src (RShiftCntV shift))); ins_cost(INSN_COST); - format %{ "sshr $dst, $src, $shift\t# vector (16B)" %} + format %{ "sshr $dst, $src, $shift\t# vector (16B)" %} ins_encode %{ int sh = (int)$shift$$constant; if (sh >= 8) sh = 7; __ sshr(as_FloatRegister($dst$$reg), __ T16B, - as_FloatRegister($src$$reg), sh); + as_FloatRegister($src$$reg), sh); %} ins_pipe(vshift128_imm); %} instruct vsrl8B_imm(vecD dst, vecD src, immI shift) %{ - predicate(n->as_Vector()->length() == 4 || - n->as_Vector()->length() == 8); + predicate((n->as_Vector()->length() == 4 || n->as_Vector()->length() == 8) && + assert_not_var_shift(n)); match(Set dst (URShiftVB src (RShiftCntV shift))); ins_cost(INSN_COST); - format %{ "ushr $dst, $src, $shift\t# vector (8B)" %} + format %{ "ushr $dst, $src, $shift\t# vector (8B)" %} ins_encode %{ int sh = (int)$shift$$constant; if (sh >= 8) { @@ -4623,17 +4715,17 @@ instruct vsrl8B_imm(vecD dst, vecD src, immI shift) %{ as_FloatRegister($src$$reg)); } else { __ ushr(as_FloatRegister($dst$$reg), __ T8B, - as_FloatRegister($src$$reg), sh); + as_FloatRegister($src$$reg), sh); } %} ins_pipe(vshift64_imm); %} instruct vsrl16B_imm(vecX dst, vecX src, immI shift) %{ - predicate(n->as_Vector()->length() == 16); + predicate(n->as_Vector()->length() == 16 && assert_not_var_shift(n)); match(Set dst (URShiftVB src (RShiftCntV shift))); ins_cost(INSN_COST); - format %{ "ushr $dst, $src, $shift\t# vector (16B)" %} + format %{ "ushr $dst, $src, $shift\t# vector (16B)" %} ins_encode %{ int sh = (int)$shift$$constant; if (sh >= 8) { @@ -4642,15 +4734,14 @@ instruct vsrl16B_imm(vecX dst, vecX src, immI shift) %{ as_FloatRegister($src$$reg)); } else { __ ushr(as_FloatRegister($dst$$reg), __ T16B, - as_FloatRegister($src$$reg), sh); + as_FloatRegister($src$$reg), sh); } %} ins_pipe(vshift128_imm); %} instruct vsll4S(vecD dst, vecD src, vecD shift) %{ - predicate(n->as_Vector()->length() == 2 || - n->as_Vector()->length() == 4); + predicate(n->as_Vector()->length() == 2 || n->as_Vector()->length() == 4); match(Set dst (LShiftVS src shift)); ins_cost(INSN_COST); format %{ "sshl $dst,$src,$shift\t# vector (4H)" %} @@ -4675,82 +4766,136 @@ instruct vsll8S(vecX dst, vecX src, vecX shift) %{ ins_pipe(vshift128); %} -instruct vsra4S(vecD dst, vecD src, vecD shift, vecD tmp) %{ - predicate(n->as_Vector()->length() == 2 || - n->as_Vector()->length() == 4); +instruct vsra4S(vecD dst, vecD src, vecD shift) %{ + predicate((n->as_Vector()->length() == 2 || n->as_Vector()->length() == 4) && + !n->as_ShiftV()->is_var_shift()); match(Set dst (RShiftVS src shift)); ins_cost(INSN_COST); - effect(TEMP tmp); - format %{ "negr $tmp,$shift\t" - "sshl $dst,$src,$tmp\t# vector (4H)" %} + format %{ "sshl $dst,$src,$shift\t# vector (4H)" %} + ins_encode %{ + __ sshl(as_FloatRegister($dst$$reg), __ T4H, + as_FloatRegister($src$$reg), + as_FloatRegister($shift$$reg)); + %} + ins_pipe(vshift64); +%} + +instruct vsra4S_var(vecD dst, vecD src, vecD shift) %{ + predicate((n->as_Vector()->length() == 2 || n->as_Vector()->length() == 4) && + n->as_ShiftV()->is_var_shift()); + match(Set dst (RShiftVS src shift)); + ins_cost(INSN_COST * 2); + effect(TEMP_DEF dst); + format %{ "negr $dst,$shift\t" + "sshl $dst,$src,$dst\t# vector (4H)" %} ins_encode %{ - __ negr(as_FloatRegister($tmp$$reg), __ T8B, + __ negr(as_FloatRegister($dst$$reg), __ T8B, as_FloatRegister($shift$$reg)); __ sshl(as_FloatRegister($dst$$reg), __ T4H, as_FloatRegister($src$$reg), - as_FloatRegister($tmp$$reg)); + as_FloatRegister($dst$$reg)); %} ins_pipe(vshift64); %} -instruct vsra8S(vecX dst, vecX src, vecX shift, vecX tmp) %{ - predicate(n->as_Vector()->length() == 8); +instruct vsra8S(vecX dst, vecX src, vecX shift) %{ + predicate(n->as_Vector()->length() == 8 && !n->as_ShiftV()->is_var_shift()); match(Set dst (RShiftVS src shift)); ins_cost(INSN_COST); - effect(TEMP tmp); - format %{ "negr $tmp,$shift\t" - "sshl $dst,$src,$tmp\t# vector (8H)" %} + format %{ "sshl $dst,$src,$shift\t# vector (8H)" %} ins_encode %{ - __ negr(as_FloatRegister($tmp$$reg), __ T16B, + __ sshl(as_FloatRegister($dst$$reg), __ T8H, + as_FloatRegister($src$$reg), + as_FloatRegister($shift$$reg)); + %} + ins_pipe(vshift128); +%} + +instruct vsra8S_var(vecX dst, vecX src, vecX shift) %{ + predicate(n->as_Vector()->length() == 8 && n->as_ShiftV()->is_var_shift()); + match(Set dst (RShiftVS src shift)); + ins_cost(INSN_COST * 2); + effect(TEMP_DEF dst); + format %{ "negr $dst,$shift\t" + "sshl $dst,$src,$dst\t# vector (8H)" %} + ins_encode %{ + __ negr(as_FloatRegister($dst$$reg), __ T16B, as_FloatRegister($shift$$reg)); __ sshl(as_FloatRegister($dst$$reg), __ T8H, as_FloatRegister($src$$reg), - as_FloatRegister($tmp$$reg)); + as_FloatRegister($dst$$reg)); %} ins_pipe(vshift128); %} -instruct vsrl4S(vecD dst, vecD src, vecD shift, vecD tmp) %{ - predicate(n->as_Vector()->length() == 2 || - n->as_Vector()->length() == 4); +instruct vsrl4S(vecD dst, vecD src, vecD shift) %{ + predicate((n->as_Vector()->length() == 2 || n->as_Vector()->length() == 4) && + !n->as_ShiftV()->is_var_shift()); match(Set dst (URShiftVS src shift)); ins_cost(INSN_COST); - effect(TEMP tmp); - format %{ "negr $tmp,$shift\t" - "ushl $dst,$src,$tmp\t# vector (4H)" %} + format %{ "ushl $dst,$src,$shift\t# vector (4H)" %} + ins_encode %{ + __ ushl(as_FloatRegister($dst$$reg), __ T4H, + as_FloatRegister($src$$reg), + as_FloatRegister($shift$$reg)); + %} + ins_pipe(vshift64); +%} + +instruct vsrl4S_var(vecD dst, vecD src, vecD shift) %{ + predicate((n->as_Vector()->length() == 2 || n->as_Vector()->length() == 4) && + n->as_ShiftV()->is_var_shift()); + match(Set dst (URShiftVS src shift)); + ins_cost(INSN_COST * 2); + effect(TEMP_DEF dst); + format %{ "negr $dst,$shift\t" + "ushl $dst,$src,$dst\t# vector (4H)" %} ins_encode %{ - __ negr(as_FloatRegister($tmp$$reg), __ T8B, + __ negr(as_FloatRegister($dst$$reg), __ T8B, as_FloatRegister($shift$$reg)); __ ushl(as_FloatRegister($dst$$reg), __ T4H, as_FloatRegister($src$$reg), - as_FloatRegister($tmp$$reg)); + as_FloatRegister($dst$$reg)); %} ins_pipe(vshift64); %} -instruct vsrl8S(vecX dst, vecX src, vecX shift, vecX tmp) %{ - predicate(n->as_Vector()->length() == 8); +instruct vsrl8S(vecX dst, vecX src, vecX shift) %{ + predicate(n->as_Vector()->length() == 8 && !n->as_ShiftV()->is_var_shift()); match(Set dst (URShiftVS src shift)); ins_cost(INSN_COST); - effect(TEMP tmp); - format %{ "negr $tmp,$shift\t" - "ushl $dst,$src,$tmp\t# vector (8H)" %} + format %{ "ushl $dst,$src,$shift\t# vector (8H)" %} ins_encode %{ - __ negr(as_FloatRegister($tmp$$reg), __ T16B, + __ ushl(as_FloatRegister($dst$$reg), __ T8H, + as_FloatRegister($src$$reg), + as_FloatRegister($shift$$reg)); + %} + ins_pipe(vshift128); +%} + +instruct vsrl8S_var(vecX dst, vecX src, vecX shift) %{ + predicate(n->as_Vector()->length() == 8 && n->as_ShiftV()->is_var_shift()); + match(Set dst (URShiftVS src shift)); + ins_cost(INSN_COST * 2); + effect(TEMP_DEF dst); + format %{ "negr $dst,$shift\t" + "ushl $dst,$src,$dst\t# vector (8H)" %} + ins_encode %{ + __ negr(as_FloatRegister($dst$$reg), __ T16B, as_FloatRegister($shift$$reg)); __ ushl(as_FloatRegister($dst$$reg), __ T8H, as_FloatRegister($src$$reg), - as_FloatRegister($tmp$$reg)); + as_FloatRegister($dst$$reg)); %} ins_pipe(vshift128); %} instruct vsll4S_imm(vecD dst, vecD src, immI shift) %{ - predicate(n->as_Vector()->length() == 2 || - n->as_Vector()->length() == 4); + predicate((n->as_Vector()->length() == 2 || n->as_Vector()->length() == 4) && + assert_not_var_shift(n)); match(Set dst (LShiftVS src (LShiftCntV shift))); ins_cost(INSN_COST); - format %{ "shl $dst, $src, $shift\t# vector (4H)" %} + format %{ "shl $dst, $src, $shift\t# vector (4H)" %} ins_encode %{ int sh = (int)$shift$$constant; if (sh >= 16) { @@ -4766,10 +4911,10 @@ instruct vsll4S_imm(vecD dst, vecD src, immI shift) %{ %} instruct vsll8S_imm(vecX dst, vecX src, immI shift) %{ - predicate(n->as_Vector()->length() == 8); + predicate(n->as_Vector()->length() == 8 && assert_not_var_shift(n)); match(Set dst (LShiftVS src (LShiftCntV shift))); ins_cost(INSN_COST); - format %{ "shl $dst, $src, $shift\t# vector (8H)" %} + format %{ "shl $dst, $src, $shift\t# vector (8H)" %} ins_encode %{ int sh = (int)$shift$$constant; if (sh >= 16) { @@ -4785,40 +4930,40 @@ instruct vsll8S_imm(vecX dst, vecX src, immI shift) %{ %} instruct vsra4S_imm(vecD dst, vecD src, immI shift) %{ - predicate(n->as_Vector()->length() == 2 || - n->as_Vector()->length() == 4); + predicate((n->as_Vector()->length() == 2 || n->as_Vector()->length() == 4) && + assert_not_var_shift(n)); match(Set dst (RShiftVS src (RShiftCntV shift))); ins_cost(INSN_COST); - format %{ "sshr $dst, $src, $shift\t# vector (4H)" %} + format %{ "sshr $dst, $src, $shift\t# vector (4H)" %} ins_encode %{ int sh = (int)$shift$$constant; if (sh >= 16) sh = 15; __ sshr(as_FloatRegister($dst$$reg), __ T4H, - as_FloatRegister($src$$reg), sh); + as_FloatRegister($src$$reg), sh); %} ins_pipe(vshift64_imm); %} instruct vsra8S_imm(vecX dst, vecX src, immI shift) %{ - predicate(n->as_Vector()->length() == 8); + predicate(n->as_Vector()->length() == 8 && assert_not_var_shift(n)); match(Set dst (RShiftVS src (RShiftCntV shift))); ins_cost(INSN_COST); - format %{ "sshr $dst, $src, $shift\t# vector (8H)" %} + format %{ "sshr $dst, $src, $shift\t# vector (8H)" %} ins_encode %{ int sh = (int)$shift$$constant; if (sh >= 16) sh = 15; __ sshr(as_FloatRegister($dst$$reg), __ T8H, - as_FloatRegister($src$$reg), sh); + as_FloatRegister($src$$reg), sh); %} ins_pipe(vshift128_imm); %} instruct vsrl4S_imm(vecD dst, vecD src, immI shift) %{ - predicate(n->as_Vector()->length() == 2 || - n->as_Vector()->length() == 4); + predicate((n->as_Vector()->length() == 2 || n->as_Vector()->length() == 4) && + assert_not_var_shift(n)); match(Set dst (URShiftVS src (RShiftCntV shift))); ins_cost(INSN_COST); - format %{ "ushr $dst, $src, $shift\t# vector (4H)" %} + format %{ "ushr $dst, $src, $shift\t# vector (4H)" %} ins_encode %{ int sh = (int)$shift$$constant; if (sh >= 16) { @@ -4827,17 +4972,17 @@ instruct vsrl4S_imm(vecD dst, vecD src, immI shift) %{ as_FloatRegister($src$$reg)); } else { __ ushr(as_FloatRegister($dst$$reg), __ T4H, - as_FloatRegister($src$$reg), sh); + as_FloatRegister($src$$reg), sh); } %} ins_pipe(vshift64_imm); %} instruct vsrl8S_imm(vecX dst, vecX src, immI shift) %{ - predicate(n->as_Vector()->length() == 8); + predicate(n->as_Vector()->length() == 8 && assert_not_var_shift(n)); match(Set dst (URShiftVS src (RShiftCntV shift))); ins_cost(INSN_COST); - format %{ "ushr $dst, $src, $shift\t# vector (8H)" %} + format %{ "ushr $dst, $src, $shift\t# vector (8H)" %} ins_encode %{ int sh = (int)$shift$$constant; if (sh >= 16) { @@ -4846,7 +4991,7 @@ instruct vsrl8S_imm(vecX dst, vecX src, immI shift) %{ as_FloatRegister($src$$reg)); } else { __ ushr(as_FloatRegister($dst$$reg), __ T8H, - as_FloatRegister($src$$reg), sh); + as_FloatRegister($src$$reg), sh); } %} ins_pipe(vshift128_imm); @@ -4878,79 +5023,131 @@ instruct vsll4I(vecX dst, vecX src, vecX shift) %{ ins_pipe(vshift128); %} -instruct vsra2I(vecD dst, vecD src, vecD shift, vecD tmp) %{ - predicate(n->as_Vector()->length() == 2); +instruct vsra2I(vecD dst, vecD src, vecD shift) %{ + predicate(n->as_Vector()->length() == 2 && !n->as_ShiftV()->is_var_shift()); match(Set dst (RShiftVI src shift)); ins_cost(INSN_COST); - effect(TEMP tmp); - format %{ "negr $tmp,$shift\t" - "sshl $dst,$src,$tmp\t# vector (2S)" %} + format %{ "sshl $dst,$src,$shift\t# vector (2S)" %} + ins_encode %{ + __ sshl(as_FloatRegister($dst$$reg), __ T2S, + as_FloatRegister($src$$reg), + as_FloatRegister($shift$$reg)); + %} + ins_pipe(vshift64); +%} + +instruct vsra2I_var(vecD dst, vecD src, vecD shift) %{ + predicate(n->as_Vector()->length() == 2 && n->as_ShiftV()->is_var_shift()); + match(Set dst (RShiftVI src shift)); + ins_cost(INSN_COST * 2); + effect(TEMP_DEF dst); + format %{ "negr $dst,$shift\t" + "sshl $dst,$src,$dst\t# vector (2S)" %} ins_encode %{ - __ negr(as_FloatRegister($tmp$$reg), __ T8B, + __ negr(as_FloatRegister($dst$$reg), __ T8B, as_FloatRegister($shift$$reg)); __ sshl(as_FloatRegister($dst$$reg), __ T2S, as_FloatRegister($src$$reg), - as_FloatRegister($tmp$$reg)); + as_FloatRegister($dst$$reg)); %} ins_pipe(vshift64); %} -instruct vsra4I(vecX dst, vecX src, vecX shift, vecX tmp) %{ - predicate(n->as_Vector()->length() == 4); +instruct vsra4I(vecX dst, vecX src, vecX shift) %{ + predicate(n->as_Vector()->length() == 4 && !n->as_ShiftV()->is_var_shift()); match(Set dst (RShiftVI src shift)); ins_cost(INSN_COST); - effect(TEMP tmp); - format %{ "negr $tmp,$shift\t" - "sshl $dst,$src,$tmp\t# vector (4S)" %} + format %{ "sshl $dst,$src,$shift\t# vector (4S)" %} ins_encode %{ - __ negr(as_FloatRegister($tmp$$reg), __ T16B, + __ sshl(as_FloatRegister($dst$$reg), __ T4S, + as_FloatRegister($src$$reg), + as_FloatRegister($shift$$reg)); + %} + ins_pipe(vshift128); +%} + +instruct vsra4I_var(vecX dst, vecX src, vecX shift) %{ + predicate(n->as_Vector()->length() == 4 && n->as_ShiftV()->is_var_shift()); + match(Set dst (RShiftVI src shift)); + ins_cost(INSN_COST * 2); + effect(TEMP_DEF dst); + format %{ "negr $dst,$shift\t" + "sshl $dst,$src,$dst\t# vector (4S)" %} + ins_encode %{ + __ negr(as_FloatRegister($dst$$reg), __ T16B, as_FloatRegister($shift$$reg)); __ sshl(as_FloatRegister($dst$$reg), __ T4S, as_FloatRegister($src$$reg), - as_FloatRegister($tmp$$reg)); + as_FloatRegister($dst$$reg)); %} ins_pipe(vshift128); %} -instruct vsrl2I(vecD dst, vecD src, vecD shift, vecD tmp) %{ - predicate(n->as_Vector()->length() == 2); +instruct vsrl2I(vecD dst, vecD src, vecD shift) %{ + predicate(n->as_Vector()->length() == 2 && !n->as_ShiftV()->is_var_shift()); match(Set dst (URShiftVI src shift)); ins_cost(INSN_COST); - effect(TEMP tmp); - format %{ "negr $tmp,$shift\t" - "ushl $dst,$src,$tmp\t# vector (2S)" %} + format %{ "ushl $dst,$src,$shift\t# vector (2S)" %} + ins_encode %{ + __ ushl(as_FloatRegister($dst$$reg), __ T2S, + as_FloatRegister($src$$reg), + as_FloatRegister($shift$$reg)); + %} + ins_pipe(vshift64); +%} + +instruct vsrl2I_var(vecD dst, vecD src, vecD shift) %{ + predicate(n->as_Vector()->length() == 2 && n->as_ShiftV()->is_var_shift()); + match(Set dst (URShiftVI src shift)); + ins_cost(INSN_COST * 2); + effect(TEMP_DEF dst); + format %{ "negr $dst,$shift\t" + "ushl $dst,$src,$dst\t# vector (2S)" %} ins_encode %{ - __ negr(as_FloatRegister($tmp$$reg), __ T8B, + __ negr(as_FloatRegister($dst$$reg), __ T8B, as_FloatRegister($shift$$reg)); __ ushl(as_FloatRegister($dst$$reg), __ T2S, as_FloatRegister($src$$reg), - as_FloatRegister($tmp$$reg)); + as_FloatRegister($dst$$reg)); %} ins_pipe(vshift64); %} -instruct vsrl4I(vecX dst, vecX src, vecX shift, vecX tmp) %{ - predicate(n->as_Vector()->length() == 4); +instruct vsrl4I(vecX dst, vecX src, vecX shift) %{ + predicate(n->as_Vector()->length() == 4 && !n->as_ShiftV()->is_var_shift()); match(Set dst (URShiftVI src shift)); ins_cost(INSN_COST); - effect(TEMP tmp); - format %{ "negr $tmp,$shift\t" - "ushl $dst,$src,$tmp\t# vector (4S)" %} + format %{ "ushl $dst,$src,$shift\t# vector (4S)" %} ins_encode %{ - __ negr(as_FloatRegister($tmp$$reg), __ T16B, + __ ushl(as_FloatRegister($dst$$reg), __ T4S, + as_FloatRegister($src$$reg), + as_FloatRegister($shift$$reg)); + %} + ins_pipe(vshift128); +%} + +instruct vsrl4I_var(vecX dst, vecX src, vecX shift) %{ + predicate(n->as_Vector()->length() == 4 && n->as_ShiftV()->is_var_shift()); + match(Set dst (URShiftVI src shift)); + ins_cost(INSN_COST * 2); + effect(TEMP_DEF dst); + format %{ "negr $dst,$shift\t" + "ushl $dst,$src,$dst\t# vector (4S)" %} + ins_encode %{ + __ negr(as_FloatRegister($dst$$reg), __ T16B, as_FloatRegister($shift$$reg)); __ ushl(as_FloatRegister($dst$$reg), __ T4S, as_FloatRegister($src$$reg), - as_FloatRegister($tmp$$reg)); + as_FloatRegister($dst$$reg)); %} ins_pipe(vshift128); %} instruct vsll2I_imm(vecD dst, vecD src, immI shift) %{ - predicate(n->as_Vector()->length() == 2); + predicate(n->as_Vector()->length() == 2 && assert_not_var_shift(n)); match(Set dst (LShiftVI src (LShiftCntV shift))); ins_cost(INSN_COST); - format %{ "shl $dst, $src, $shift\t# vector (2S)" %} + format %{ "shl $dst, $src, $shift\t# vector (2S)" %} ins_encode %{ __ shl(as_FloatRegister($dst$$reg), __ T2S, as_FloatRegister($src$$reg), @@ -4960,10 +5157,10 @@ instruct vsll2I_imm(vecD dst, vecD src, immI shift) %{ %} instruct vsll4I_imm(vecX dst, vecX src, immI shift) %{ - predicate(n->as_Vector()->length() == 4); + predicate(n->as_Vector()->length() == 4 && assert_not_var_shift(n)); match(Set dst (LShiftVI src (LShiftCntV shift))); ins_cost(INSN_COST); - format %{ "shl $dst, $src, $shift\t# vector (4S)" %} + format %{ "shl $dst, $src, $shift\t# vector (4S)" %} ins_encode %{ __ shl(as_FloatRegister($dst$$reg), __ T4S, as_FloatRegister($src$$reg), @@ -4973,10 +5170,10 @@ instruct vsll4I_imm(vecX dst, vecX src, immI shift) %{ %} instruct vsra2I_imm(vecD dst, vecD src, immI shift) %{ - predicate(n->as_Vector()->length() == 2); + predicate(n->as_Vector()->length() == 2 && assert_not_var_shift(n)); match(Set dst (RShiftVI src (RShiftCntV shift))); ins_cost(INSN_COST); - format %{ "sshr $dst, $src, $shift\t# vector (2S)" %} + format %{ "sshr $dst, $src, $shift\t# vector (2S)" %} ins_encode %{ __ sshr(as_FloatRegister($dst$$reg), __ T2S, as_FloatRegister($src$$reg), @@ -4986,10 +5183,10 @@ instruct vsra2I_imm(vecD dst, vecD src, immI shift) %{ %} instruct vsra4I_imm(vecX dst, vecX src, immI shift) %{ - predicate(n->as_Vector()->length() == 4); + predicate(n->as_Vector()->length() == 4 && assert_not_var_shift(n)); match(Set dst (RShiftVI src (RShiftCntV shift))); ins_cost(INSN_COST); - format %{ "sshr $dst, $src, $shift\t# vector (4S)" %} + format %{ "sshr $dst, $src, $shift\t# vector (4S)" %} ins_encode %{ __ sshr(as_FloatRegister($dst$$reg), __ T4S, as_FloatRegister($src$$reg), @@ -4999,10 +5196,10 @@ instruct vsra4I_imm(vecX dst, vecX src, immI shift) %{ %} instruct vsrl2I_imm(vecD dst, vecD src, immI shift) %{ - predicate(n->as_Vector()->length() == 2); + predicate(n->as_Vector()->length() == 2 && assert_not_var_shift(n)); match(Set dst (URShiftVI src (RShiftCntV shift))); ins_cost(INSN_COST); - format %{ "ushr $dst, $src, $shift\t# vector (2S)" %} + format %{ "ushr $dst, $src, $shift\t# vector (2S)" %} ins_encode %{ __ ushr(as_FloatRegister($dst$$reg), __ T2S, as_FloatRegister($src$$reg), @@ -5012,10 +5209,10 @@ instruct vsrl2I_imm(vecD dst, vecD src, immI shift) %{ %} instruct vsrl4I_imm(vecX dst, vecX src, immI shift) %{ - predicate(n->as_Vector()->length() == 4); + predicate(n->as_Vector()->length() == 4 && assert_not_var_shift(n)); match(Set dst (URShiftVI src (RShiftCntV shift))); ins_cost(INSN_COST); - format %{ "ushr $dst, $src, $shift\t# vector (4S)" %} + format %{ "ushr $dst, $src, $shift\t# vector (4S)" %} ins_encode %{ __ ushr(as_FloatRegister($dst$$reg), __ T4S, as_FloatRegister($src$$reg), @@ -5037,45 +5234,71 @@ instruct vsll2L(vecX dst, vecX src, vecX shift) %{ ins_pipe(vshift128); %} -instruct vsra2L(vecX dst, vecX src, vecX shift, vecX tmp) %{ - predicate(n->as_Vector()->length() == 2); +instruct vsra2L(vecX dst, vecX src, vecX shift) %{ + predicate(n->as_Vector()->length() == 2 && !n->as_ShiftV()->is_var_shift()); match(Set dst (RShiftVL src shift)); ins_cost(INSN_COST); - effect(TEMP tmp); - format %{ "negr $tmp,$shift\t" - "sshl $dst,$src,$tmp\t# vector (2D)" %} + format %{ "sshl $dst,$src,$shift\t# vector (2D)" %} ins_encode %{ - __ negr(as_FloatRegister($tmp$$reg), __ T16B, + __ sshl(as_FloatRegister($dst$$reg), __ T2D, + as_FloatRegister($src$$reg), + as_FloatRegister($shift$$reg)); + %} + ins_pipe(vshift128); +%} + +instruct vsra2L_var(vecX dst, vecX src, vecX shift) %{ + predicate(n->as_Vector()->length() == 2 && n->as_ShiftV()->is_var_shift()); + match(Set dst (RShiftVL src shift)); + ins_cost(INSN_COST * 2); + effect(TEMP_DEF dst); + format %{ "negr $dst,$shift\t" + "sshl $dst,$src,$dst\t# vector (2D)" %} + ins_encode %{ + __ negr(as_FloatRegister($dst$$reg), __ T16B, as_FloatRegister($shift$$reg)); __ sshl(as_FloatRegister($dst$$reg), __ T2D, as_FloatRegister($src$$reg), - as_FloatRegister($tmp$$reg)); + as_FloatRegister($dst$$reg)); %} ins_pipe(vshift128); %} -instruct vsrl2L(vecX dst, vecX src, vecX shift, vecX tmp) %{ - predicate(n->as_Vector()->length() == 2); +instruct vsrl2L(vecX dst, vecX src, vecX shift) %{ + predicate(n->as_Vector()->length() == 2 && !n->as_ShiftV()->is_var_shift()); match(Set dst (URShiftVL src shift)); ins_cost(INSN_COST); - effect(TEMP tmp); - format %{ "negr $tmp,$shift\t" - "ushl $dst,$src,$tmp\t# vector (2D)" %} + format %{ "ushl $dst,$src,$shift\t# vector (2D)" %} + ins_encode %{ + __ ushl(as_FloatRegister($dst$$reg), __ T2D, + as_FloatRegister($src$$reg), + as_FloatRegister($shift$$reg)); + %} + ins_pipe(vshift128); +%} + +instruct vsrl2L_var(vecX dst, vecX src, vecX shift) %{ + predicate(n->as_Vector()->length() == 2 && n->as_ShiftV()->is_var_shift()); + match(Set dst (URShiftVL src shift)); + ins_cost(INSN_COST * 2); + effect(TEMP_DEF dst); + format %{ "negr $dst,$shift\t" + "ushl $dst,$src,$dst\t# vector (2D)" %} ins_encode %{ - __ negr(as_FloatRegister($tmp$$reg), __ T16B, + __ negr(as_FloatRegister($dst$$reg), __ T16B, as_FloatRegister($shift$$reg)); __ ushl(as_FloatRegister($dst$$reg), __ T2D, as_FloatRegister($src$$reg), - as_FloatRegister($tmp$$reg)); + as_FloatRegister($dst$$reg)); %} ins_pipe(vshift128); %} instruct vsll2L_imm(vecX dst, vecX src, immI shift) %{ - predicate(n->as_Vector()->length() == 2); + predicate(n->as_Vector()->length() == 2 && assert_not_var_shift(n)); match(Set dst (LShiftVL src (LShiftCntV shift))); ins_cost(INSN_COST); - format %{ "shl $dst, $src, $shift\t# vector (2D)" %} + format %{ "shl $dst, $src, $shift\t# vector (2D)" %} ins_encode %{ __ shl(as_FloatRegister($dst$$reg), __ T2D, as_FloatRegister($src$$reg), @@ -5085,10 +5308,10 @@ instruct vsll2L_imm(vecX dst, vecX src, immI shift) %{ %} instruct vsra2L_imm(vecX dst, vecX src, immI shift) %{ - predicate(n->as_Vector()->length() == 2); + predicate(n->as_Vector()->length() == 2 && assert_not_var_shift(n)); match(Set dst (RShiftVL src (RShiftCntV shift))); ins_cost(INSN_COST); - format %{ "sshr $dst, $src, $shift\t# vector (2D)" %} + format %{ "sshr $dst, $src, $shift\t# vector (2D)" %} ins_encode %{ __ sshr(as_FloatRegister($dst$$reg), __ T2D, as_FloatRegister($src$$reg), @@ -5098,10 +5321,10 @@ instruct vsra2L_imm(vecX dst, vecX src, immI shift) %{ %} instruct vsrl2L_imm(vecX dst, vecX src, immI shift) %{ - predicate(n->as_Vector()->length() == 2); + predicate(n->as_Vector()->length() == 2 && assert_not_var_shift(n)); match(Set dst (URShiftVL src (RShiftCntV shift))); ins_cost(INSN_COST); - format %{ "ushr $dst, $src, $shift\t# vector (2D)" %} + format %{ "ushr $dst, $src, $shift\t# vector (2D)" %} ins_encode %{ __ ushr(as_FloatRegister($dst$$reg), __ T2D, as_FloatRegister($src$$reg), @@ -5114,12 +5337,12 @@ instruct vsraa8B_imm(vecD dst, vecD src, immI shift) %{ predicate(n->as_Vector()->length() == 8); match(Set dst (AddVB dst (RShiftVB src (RShiftCntV shift)))); ins_cost(INSN_COST); - format %{ "ssra $dst, $src, $shift\t# vector (8B)" %} + format %{ "ssra $dst, $src, $shift\t# vector (8B)" %} ins_encode %{ int sh = (int)$shift$$constant; if (sh >= 8) sh = 7; __ ssra(as_FloatRegister($dst$$reg), __ T8B, - as_FloatRegister($src$$reg), sh); + as_FloatRegister($src$$reg), sh); %} ins_pipe(vshift64_imm); %} @@ -5128,12 +5351,12 @@ instruct vsraa16B_imm(vecX dst, vecX src, immI shift) %{ predicate(n->as_Vector()->length() == 16); match(Set dst (AddVB dst (RShiftVB src (RShiftCntV shift)))); ins_cost(INSN_COST); - format %{ "ssra $dst, $src, $shift\t# vector (16B)" %} + format %{ "ssra $dst, $src, $shift\t# vector (16B)" %} ins_encode %{ int sh = (int)$shift$$constant; if (sh >= 8) sh = 7; __ ssra(as_FloatRegister($dst$$reg), __ T16B, - as_FloatRegister($src$$reg), sh); + as_FloatRegister($src$$reg), sh); %} ins_pipe(vshift128_imm); %} @@ -5142,12 +5365,12 @@ instruct vsraa4S_imm(vecD dst, vecD src, immI shift) %{ predicate(n->as_Vector()->length() == 4); match(Set dst (AddVS dst (RShiftVS src (RShiftCntV shift)))); ins_cost(INSN_COST); - format %{ "ssra $dst, $src, $shift\t# vector (4H)" %} + format %{ "ssra $dst, $src, $shift\t# vector (4H)" %} ins_encode %{ int sh = (int)$shift$$constant; if (sh >= 16) sh = 15; __ ssra(as_FloatRegister($dst$$reg), __ T4H, - as_FloatRegister($src$$reg), sh); + as_FloatRegister($src$$reg), sh); %} ins_pipe(vshift64_imm); %} @@ -5156,12 +5379,12 @@ instruct vsraa8S_imm(vecX dst, vecX src, immI shift) %{ predicate(n->as_Vector()->length() == 8); match(Set dst (AddVS dst (RShiftVS src (RShiftCntV shift)))); ins_cost(INSN_COST); - format %{ "ssra $dst, $src, $shift\t# vector (8H)" %} + format %{ "ssra $dst, $src, $shift\t# vector (8H)" %} ins_encode %{ int sh = (int)$shift$$constant; if (sh >= 16) sh = 15; __ ssra(as_FloatRegister($dst$$reg), __ T8H, - as_FloatRegister($src$$reg), sh); + as_FloatRegister($src$$reg), sh); %} ins_pipe(vshift128_imm); %} @@ -5170,7 +5393,7 @@ instruct vsraa2I_imm(vecD dst, vecD src, immI shift) %{ predicate(n->as_Vector()->length() == 2); match(Set dst (AddVI dst (RShiftVI src (RShiftCntV shift)))); ins_cost(INSN_COST); - format %{ "ssra $dst, $src, $shift\t# vector (2S)" %} + format %{ "ssra $dst, $src, $shift\t# vector (2S)" %} ins_encode %{ __ ssra(as_FloatRegister($dst$$reg), __ T2S, as_FloatRegister($src$$reg), @@ -5183,7 +5406,7 @@ instruct vsraa4I_imm(vecX dst, vecX src, immI shift) %{ predicate(n->as_Vector()->length() == 4); match(Set dst (AddVI dst (RShiftVI src (RShiftCntV shift)))); ins_cost(INSN_COST); - format %{ "ssra $dst, $src, $shift\t# vector (4S)" %} + format %{ "ssra $dst, $src, $shift\t# vector (4S)" %} ins_encode %{ __ ssra(as_FloatRegister($dst$$reg), __ T4S, as_FloatRegister($src$$reg), @@ -5196,7 +5419,7 @@ instruct vsraa2L_imm(vecX dst, vecX src, immI shift) %{ predicate(n->as_Vector()->length() == 2); match(Set dst (AddVL dst (RShiftVL src (RShiftCntV shift)))); ins_cost(INSN_COST); - format %{ "ssra $dst, $src, $shift\t# vector (2D)" %} + format %{ "ssra $dst, $src, $shift\t# vector (2D)" %} ins_encode %{ __ ssra(as_FloatRegister($dst$$reg), __ T2D, as_FloatRegister($src$$reg), @@ -5209,12 +5432,12 @@ instruct vsrla8B_imm(vecD dst, vecD src, immI shift) %{ predicate(n->as_Vector()->length() == 8); match(Set dst (AddVB dst (URShiftVB src (RShiftCntV shift)))); ins_cost(INSN_COST); - format %{ "usra $dst, $src, $shift\t# vector (8B)" %} + format %{ "usra $dst, $src, $shift\t# vector (8B)" %} ins_encode %{ int sh = (int)$shift$$constant; if (sh < 8) { __ usra(as_FloatRegister($dst$$reg), __ T8B, - as_FloatRegister($src$$reg), sh); + as_FloatRegister($src$$reg), sh); } %} ins_pipe(vshift64_imm); @@ -5224,12 +5447,12 @@ instruct vsrla16B_imm(vecX dst, vecX src, immI shift) %{ predicate(n->as_Vector()->length() == 16); match(Set dst (AddVB dst (URShiftVB src (RShiftCntV shift)))); ins_cost(INSN_COST); - format %{ "usra $dst, $src, $shift\t# vector (16B)" %} + format %{ "usra $dst, $src, $shift\t# vector (16B)" %} ins_encode %{ int sh = (int)$shift$$constant; if (sh < 8) { __ usra(as_FloatRegister($dst$$reg), __ T16B, - as_FloatRegister($src$$reg), sh); + as_FloatRegister($src$$reg), sh); } %} ins_pipe(vshift128_imm); @@ -5239,12 +5462,12 @@ instruct vsrla4S_imm(vecD dst, vecD src, immI shift) %{ predicate(n->as_Vector()->length() == 4); match(Set dst (AddVS dst (URShiftVS src (RShiftCntV shift)))); ins_cost(INSN_COST); - format %{ "usra $dst, $src, $shift\t# vector (4H)" %} + format %{ "usra $dst, $src, $shift\t# vector (4H)" %} ins_encode %{ int sh = (int)$shift$$constant; if (sh < 16) { __ usra(as_FloatRegister($dst$$reg), __ T4H, - as_FloatRegister($src$$reg), sh); + as_FloatRegister($src$$reg), sh); } %} ins_pipe(vshift64_imm); @@ -5254,12 +5477,12 @@ instruct vsrla8S_imm(vecX dst, vecX src, immI shift) %{ predicate(n->as_Vector()->length() == 8); match(Set dst (AddVS dst (URShiftVS src (RShiftCntV shift)))); ins_cost(INSN_COST); - format %{ "usra $dst, $src, $shift\t# vector (8H)" %} + format %{ "usra $dst, $src, $shift\t# vector (8H)" %} ins_encode %{ int sh = (int)$shift$$constant; if (sh < 16) { __ usra(as_FloatRegister($dst$$reg), __ T8H, - as_FloatRegister($src$$reg), sh); + as_FloatRegister($src$$reg), sh); } %} ins_pipe(vshift128_imm); @@ -5269,7 +5492,7 @@ instruct vsrla2I_imm(vecD dst, vecD src, immI shift) %{ predicate(n->as_Vector()->length() == 2); match(Set dst (AddVI dst (URShiftVI src (RShiftCntV shift)))); ins_cost(INSN_COST); - format %{ "usra $dst, $src, $shift\t# vector (2S)" %} + format %{ "usra $dst, $src, $shift\t# vector (2S)" %} ins_encode %{ __ usra(as_FloatRegister($dst$$reg), __ T2S, as_FloatRegister($src$$reg), @@ -5282,7 +5505,7 @@ instruct vsrla4I_imm(vecX dst, vecX src, immI shift) %{ predicate(n->as_Vector()->length() == 4); match(Set dst (AddVI dst (URShiftVI src (RShiftCntV shift)))); ins_cost(INSN_COST); - format %{ "usra $dst, $src, $shift\t# vector (4S)" %} + format %{ "usra $dst, $src, $shift\t# vector (4S)" %} ins_encode %{ __ usra(as_FloatRegister($dst$$reg), __ T4S, as_FloatRegister($src$$reg), @@ -5295,7 +5518,7 @@ instruct vsrla2L_imm(vecX dst, vecX src, immI shift) %{ predicate(n->as_Vector()->length() == 2); match(Set dst (AddVL dst (URShiftVL src (RShiftCntV shift)))); ins_cost(INSN_COST); - format %{ "usra $dst, $src, $shift\t# vector (2D)" %} + format %{ "usra $dst, $src, $shift\t# vector (2D)" %} ins_encode %{ __ usra(as_FloatRegister($dst$$reg), __ T2D, as_FloatRegister($src$$reg), diff --git a/src/hotspot/cpu/aarch64/aarch64_neon_ad.m4 b/src/hotspot/cpu/aarch64/aarch64_neon_ad.m4 index ff94bb002fafc0d6c831a9fea239a289dcec482d..f98ddf4ee3655f91d45b07f2227b28ed8ae214eb 100644 --- a/src/hotspot/cpu/aarch64/aarch64_neon_ad.m4 +++ b/src/hotspot/cpu/aarch64/aarch64_neon_ad.m4 @@ -1,5 +1,5 @@ -// Copyright (c) 2020, 2021, Oracle and/or its affiliates. All rights reserved. -// Copyright (c) 2020, 2021, Arm Limited. All rights reserved. +// Copyright (c) 2020, 2022, Oracle and/or its affiliates. All rights reserved. +// Copyright (c) 2020, 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 @@ -1972,223 +1972,277 @@ VLOGICAL(xor, eor, xor, Xor, 16, B, X) // ------------------------------ Shift --------------------------------------- dnl -define(`VSHIFTCNT', ` -instruct vshiftcnt$3$4`'(vec$5 dst, iRegIorL2I cnt) %{ - predicate(UseSVE == 0 && (ifelse($3, 8, n->as_Vector()->length_in_bytes() == 4 ||` - ')n->as_Vector()->length_in_bytes() == $3)); +define(`VSLCNT', ` +instruct vslcnt$1$2`'(vec$3 dst, iRegIorL2I cnt) %{ + predicate(UseSVE == 0 && ifelse($1, 8, + (n->as_Vector()->length_in_bytes() == 4 ||` + 'n->as_Vector()->length_in_bytes() == $1), + n->as_Vector()->length_in_bytes() == $1)); match(Set dst (LShiftCntV cnt)); - match(Set dst (RShiftCntV cnt)); - format %{ "$1 $dst, $cnt\t# shift count vector ($3$4)" %} + ins_cost(INSN_COST); + format %{ "dup $dst, $cnt\t# shift count vector ($1$2)" %} ins_encode %{ - __ $2(as_FloatRegister($dst$$reg), __ T$3$4, as_Register($cnt$$reg)); + __ dup(as_FloatRegister($dst$$reg), __ T$1$2, as_Register($cnt$$reg)); %} - ins_pipe(vdup_reg_reg`'ifelse($5, D, 64, 128)); + ins_pipe(vdup_reg_reg`'ifelse($3, D, 64, 128)); %}')dnl -dnl $1 $2 $3 $4 $5 -VSHIFTCNT(dup, dup, 8, B, D) -VSHIFTCNT(dup, dup, 16, B, X) +dnl +define(`VSRCNT', ` +instruct vsrcnt$1$2`'(vec$3 dst, iRegIorL2I cnt) %{ + predicate(UseSVE == 0 && ifelse($1, 8, + (n->as_Vector()->length_in_bytes() == 4 ||` + 'n->as_Vector()->length_in_bytes() == $1), + n->as_Vector()->length_in_bytes() == $1)); + match(Set dst (RShiftCntV cnt)); + ins_cost(INSN_COST * 2); + format %{ "negw rscratch1, $cnt\t" + "dup $dst, rscratch1\t# shift count vector ($1$2)" %} + ins_encode %{ + __ negw(rscratch1, as_Register($cnt$$reg)); + __ dup(as_FloatRegister($dst$$reg), __ T$1$2, rscratch1); + %} + ins_pipe(vdup_reg_reg`'ifelse($3, D, 64, 128)); +%}')dnl +dnl + +// Vector shift count +// Note-1: Low 8 bits of each element are used, so it doesn't matter if we +// treat it as ints or bytes here. +// Note-2: Shift value is negated for RShiftCntV additionally. See the comments +// on vsra8B rule for more details. +dnl $1 $2 $3 +VSLCNT(8, B, D) +VSLCNT(16, B, X) +VSRCNT(8, B, D) +VSRCNT(16, B, X) +dnl +define(`PREDICATE', +`ifelse($1, 8B, + ifelse($3, `', `predicate(n->as_Vector()->length() == 4 || n->as_Vector()->length() == 8);', + `predicate((n->as_Vector()->length() == 4 || n->as_Vector()->length() == 8) &&` + '$3);'), + $1, 4S, + ifelse($3, `', `predicate(n->as_Vector()->length() == 2 || n->as_Vector()->length() == 4);', + `predicate((n->as_Vector()->length() == 2 || n->as_Vector()->length() == 4) &&` + '$3);'), + ifelse($3, `', `predicate(n->as_Vector()->length() == $2);', + `predicate(n->as_Vector()->length() == $2 && $3);'))')dnl dnl define(`VSLL', ` -instruct vsll$3$4`'(vec$6 dst, vec$6 src, vec$6 shift) %{ - predicate(ifelse($3$4, 8B, n->as_Vector()->length() == 4 ||` - ', - $3$4, 4S, n->as_Vector()->length() == 2 ||` - ')n->as_Vector()->length() == $3); - match(Set dst (LShiftV$4 src shift)); +instruct vsll$1$2`'(vec$4 dst, vec$4 src, vec$4 shift) %{ + PREDICATE(`$1$2', $1, ) + match(Set dst (LShiftV$2 src shift)); ins_cost(INSN_COST); - format %{ "$1 $dst,$src,$shift\t# vector ($3$5)" %} + format %{ "sshl $dst,$src,$shift\t# vector ($1$3)" %} ins_encode %{ - __ $2(as_FloatRegister($dst$$reg), __ T$3$5, + __ sshl(as_FloatRegister($dst$$reg), __ T$1$3, as_FloatRegister($src$$reg), as_FloatRegister($shift$$reg)); %} - ins_pipe(vshift`'ifelse($6, D, 64, 128)); + ins_pipe(vshift`'ifelse($4, D, 64, 128)); %}')dnl dnl define(`VSRA', ` -instruct vsra$3$4`'(vec$6 dst, vec$6 src, vec$6 shift, vec$6 tmp) %{ - predicate(ifelse($3$4, 8B, n->as_Vector()->length() == 4 ||` - ', - $3$4, 4S, n->as_Vector()->length() == 2 ||` - ')n->as_Vector()->length() == $3); - match(Set dst (RShiftV$4 src shift)); +instruct vsra$1$2`'(vec$4 dst, vec$4 src, vec$4 shift) %{ + PREDICATE(`$1$2', $1, !n->as_ShiftV()->is_var_shift()) + match(Set dst (RShiftV$2 src shift)); ins_cost(INSN_COST); - effect(TEMP tmp); - format %{ "$1 $tmp,$shift\t" - "$2 $dst,$src,$tmp\t# vector ($3$5)" %} + format %{ "sshl $dst,$src,$shift\t# vector ($1$3)" %} ins_encode %{ - __ $1(as_FloatRegister($tmp$$reg), __ T`'ifelse($6, D, 8B, 16B), + __ sshl(as_FloatRegister($dst$$reg), __ T$1$3, + as_FloatRegister($src$$reg), as_FloatRegister($shift$$reg)); - __ $2(as_FloatRegister($dst$$reg), __ T$3$5, + %} + ins_pipe(vshift`'ifelse($4, D, 64, 128)); +%}')dnl +dnl +define(`VSRA_VAR', ` +instruct vsra$1$2_var`'(vec$4 dst, vec$4 src, vec$4 shift) %{ + PREDICATE(`$1$2', $1, n->as_ShiftV()->is_var_shift()) + match(Set dst (RShiftV$2 src shift)); + ins_cost(INSN_COST * 2); + effect(TEMP_DEF dst); + format %{ "negr $dst,$shift\t" + "sshl $dst,$src,$dst\t# vector ($1$3)" %} + ins_encode %{ + __ negr(as_FloatRegister($dst$$reg), __ T`'ifelse($4, D, 8B, 16B), + as_FloatRegister($shift$$reg)); + __ sshl(as_FloatRegister($dst$$reg), __ T$1$3, as_FloatRegister($src$$reg), - as_FloatRegister($tmp$$reg)); + as_FloatRegister($dst$$reg)); %} - ins_pipe(vshift`'ifelse($6, D, 64, 128)); + ins_pipe(vshift`'ifelse($4, D, 64, 128)); %}')dnl dnl define(`VSRL', ` -instruct vsrl$3$4`'(vec$6 dst, vec$6 src, vec$6 shift, vec$6 tmp) %{ - predicate(ifelse($3$4, 8B, n->as_Vector()->length() == 4 ||` - ', - $3$4, 4S, n->as_Vector()->length() == 2 ||` - ')n->as_Vector()->length() == $3); - match(Set dst (URShiftV$4 src shift)); +instruct vsrl$1$2`'(vec$4 dst, vec$4 src, vec$4 shift) %{ + PREDICATE(`$1$2', $1, !n->as_ShiftV()->is_var_shift()) + match(Set dst (URShiftV$2 src shift)); ins_cost(INSN_COST); - effect(TEMP tmp); - format %{ "$1 $tmp,$shift\t" - "$2 $dst,$src,$tmp\t# vector ($3$5)" %} + format %{ "ushl $dst,$src,$shift\t# vector ($1$3)" %} + ins_encode %{ + __ ushl(as_FloatRegister($dst$$reg), __ T$1$3, + as_FloatRegister($src$$reg), + as_FloatRegister($shift$$reg)); + %} + ins_pipe(vshift`'ifelse($4, D, 64, 128)); +%}')dnl +dnl +define(`VSRL_VAR', ` +instruct vsrl$1$2_var`'(vec$4 dst, vec$4 src, vec$4 shift) %{ + PREDICATE(`$1$2', $1, n->as_ShiftV()->is_var_shift()) + match(Set dst (URShiftV$2 src shift)); + ins_cost(INSN_COST * 2); + effect(TEMP_DEF dst); + format %{ "negr $dst,$shift\t" + "ushl $dst,$src,$dst\t# vector ($1$3)" %} ins_encode %{ - __ $1(as_FloatRegister($tmp$$reg), __ T`'ifelse($6, D, 8B, 16B), + __ negr(as_FloatRegister($dst$$reg), __ T`'ifelse($4, D, 8B, 16B), as_FloatRegister($shift$$reg)); - __ $2(as_FloatRegister($dst$$reg), __ T$3$5, + __ ushl(as_FloatRegister($dst$$reg), __ T$1$3, as_FloatRegister($src$$reg), - as_FloatRegister($tmp$$reg)); + as_FloatRegister($dst$$reg)); %} - ins_pipe(vshift`'ifelse($6, D, 64, 128)); + ins_pipe(vshift`'ifelse($4, D, 64, 128)); %}')dnl dnl define(`VSLL_IMM', ` -instruct vsll$3$4_imm`'(vec$6 dst, vec$6 src, immI shift) %{ - predicate(ifelse($3$4, 8B, n->as_Vector()->length() == 4 ||` - ', - $3$4, 4S, n->as_Vector()->length() == 2 ||` - ')n->as_Vector()->length() == $3); - match(Set dst (LShiftV$4 src (LShiftCntV shift))); - ins_cost(INSN_COST); - format %{ "$1 $dst, $src, $shift\t# vector ($3$5)" %} - ins_encode %{ifelse($4, B,` +instruct vsll$1$2_imm`'(vec$4 dst, vec$4 src, immI shift) %{ + PREDICATE(`$1$2', $1, assert_not_var_shift(n)) + match(Set dst (LShiftV$2 src (LShiftCntV shift))); + ins_cost(INSN_COST); + format %{ "shl $dst, $src, $shift\t# vector ($1$3)" %} + ins_encode %{ifelse($2, B,` int sh = (int)$shift$$constant; if (sh >= 8) { - __ eor(as_FloatRegister($dst$$reg), __ ifelse($6, D, T8B, T16B), + __ eor(as_FloatRegister($dst$$reg), __ ifelse($4, D, T8B, T16B), as_FloatRegister($src$$reg), as_FloatRegister($src$$reg)); } else { - __ $2(as_FloatRegister($dst$$reg), __ T$3$5, + __ shl(as_FloatRegister($dst$$reg), __ T$1$3, as_FloatRegister($src$$reg), sh); - }', $4, S,` + }', $2, S,` int sh = (int)$shift$$constant; if (sh >= 16) { - __ eor(as_FloatRegister($dst$$reg), __ ifelse($6, D, T8B, T16B), + __ eor(as_FloatRegister($dst$$reg), __ ifelse($4, D, T8B, T16B), as_FloatRegister($src$$reg), as_FloatRegister($src$$reg)); } else { - __ $2(as_FloatRegister($dst$$reg), __ T$3$5, + __ shl(as_FloatRegister($dst$$reg), __ T$1$3, as_FloatRegister($src$$reg), sh); }', ` - __ $2(as_FloatRegister($dst$$reg), __ T$3$5, + __ shl(as_FloatRegister($dst$$reg), __ T$1$3, as_FloatRegister($src$$reg), (int)$shift$$constant);') %} - ins_pipe(vshift`'ifelse($6, D, 64, 128)_imm); + ins_pipe(vshift`'ifelse($4, D, 64, 128)_imm); %}')dnl +dnl define(`VSRA_IMM', ` -instruct vsra$3$4_imm`'(vec$6 dst, vec$6 src, immI shift) %{ - predicate(ifelse($3$4, 8B, n->as_Vector()->length() == 4 ||` - ', - $3$4, 4S, n->as_Vector()->length() == 2 ||` - ')n->as_Vector()->length() == $3); - match(Set dst (RShiftV$4 src (RShiftCntV shift))); - ins_cost(INSN_COST); - format %{ "$1 $dst, $src, $shift\t# vector ($3$5)" %} - ins_encode %{ifelse($4, B,` +instruct vsra$1$2_imm`'(vec$4 dst, vec$4 src, immI shift) %{ + PREDICATE(`$1$2', $1, assert_not_var_shift(n)) + match(Set dst (RShiftV$2 src (RShiftCntV shift))); + ins_cost(INSN_COST); + format %{ "sshr $dst, $src, $shift\t# vector ($1$3)" %} + ins_encode %{ifelse($2, B,` int sh = (int)$shift$$constant; if (sh >= 8) sh = 7; - __ $2(as_FloatRegister($dst$$reg), __ T$3$5, - as_FloatRegister($src$$reg), sh);', $4, S,` + __ sshr(as_FloatRegister($dst$$reg), __ T$1$3, + as_FloatRegister($src$$reg), sh);', $2, S,` int sh = (int)$shift$$constant; if (sh >= 16) sh = 15; - __ $2(as_FloatRegister($dst$$reg), __ T$3$5, - as_FloatRegister($src$$reg), sh);', ` - __ $2(as_FloatRegister($dst$$reg), __ T$3$5, + __ sshr(as_FloatRegister($dst$$reg), __ T$1$3, + as_FloatRegister($src$$reg), sh);', ` + __ sshr(as_FloatRegister($dst$$reg), __ T$1$3, as_FloatRegister($src$$reg), (int)$shift$$constant);') %} - ins_pipe(vshift`'ifelse($6, D, 64, 128)_imm); + ins_pipe(vshift`'ifelse($4, D, 64, 128)_imm); %}')dnl dnl define(`VSRL_IMM', ` -instruct vsrl$3$4_imm`'(vec$6 dst, vec$6 src, immI shift) %{ - predicate(ifelse($3$4, 8B, n->as_Vector()->length() == 4 ||` - ', - $3$4, 4S, n->as_Vector()->length() == 2 ||` - ')n->as_Vector()->length() == $3); - match(Set dst (URShiftV$4 src (RShiftCntV shift))); - ins_cost(INSN_COST); - format %{ "$1 $dst, $src, $shift\t# vector ($3$5)" %} - ins_encode %{ifelse($4, B,` +instruct vsrl$1$2_imm`'(vec$4 dst, vec$4 src, immI shift) %{ + PREDICATE(`$1$2', $1, assert_not_var_shift(n)) + match(Set dst (URShiftV$2 src (RShiftCntV shift))); + ins_cost(INSN_COST); + format %{ "ushr $dst, $src, $shift\t# vector ($1$3)" %} + ins_encode %{ifelse($2, B,` int sh = (int)$shift$$constant; if (sh >= 8) { - __ eor(as_FloatRegister($dst$$reg), __ ifelse($6, D, T8B, T16B), + __ eor(as_FloatRegister($dst$$reg), __ ifelse($4, D, T8B, T16B), as_FloatRegister($src$$reg), as_FloatRegister($src$$reg)); } else { - __ $2(as_FloatRegister($dst$$reg), __ T$3$5, - as_FloatRegister($src$$reg), sh); - }', $4, S,` + __ ushr(as_FloatRegister($dst$$reg), __ T$1$3, + as_FloatRegister($src$$reg), sh); + }', $2, S,` int sh = (int)$shift$$constant; if (sh >= 16) { - __ eor(as_FloatRegister($dst$$reg), __ ifelse($6, D, T8B, T16B), + __ eor(as_FloatRegister($dst$$reg), __ ifelse($4, D, T8B, T16B), as_FloatRegister($src$$reg), as_FloatRegister($src$$reg)); } else { - __ $2(as_FloatRegister($dst$$reg), __ T$3$5, - as_FloatRegister($src$$reg), sh); + __ ushr(as_FloatRegister($dst$$reg), __ T$1$3, + as_FloatRegister($src$$reg), sh); }', ` - __ $2(as_FloatRegister($dst$$reg), __ T$3$5, + __ ushr(as_FloatRegister($dst$$reg), __ T$1$3, as_FloatRegister($src$$reg), (int)$shift$$constant);') %} - ins_pipe(vshift`'ifelse($6, D, 64, 128)_imm); + ins_pipe(vshift`'ifelse($4, D, 64, 128)_imm); %}')dnl dnl define(`VSRLA_IMM', ` -instruct vsrla$3$4_imm`'(vec$6 dst, vec$6 src, immI shift) %{ - predicate(n->as_Vector()->length() == $3); - match(Set dst (AddV$4 dst (URShiftV$4 src (RShiftCntV shift)))); +instruct vsrla$1$2_imm`'(vec$4 dst, vec$4 src, immI shift) %{ + predicate(n->as_Vector()->length() == $1); + match(Set dst (AddV$2 dst (URShiftV$2 src (RShiftCntV shift)))); ins_cost(INSN_COST); - format %{ "$1 $dst, $src, $shift\t# vector ($3$5)" %} - ins_encode %{ifelse($4, B,` + format %{ "usra $dst, $src, $shift\t# vector ($1$3)" %} + ins_encode %{ifelse($2, B,` int sh = (int)$shift$$constant; if (sh < 8) { - __ $2(as_FloatRegister($dst$$reg), __ T$3$5, - as_FloatRegister($src$$reg), sh); - }', $4, S,` + __ usra(as_FloatRegister($dst$$reg), __ T$1$3, + as_FloatRegister($src$$reg), sh); + }', $2, S,` int sh = (int)$shift$$constant; if (sh < 16) { - __ $2(as_FloatRegister($dst$$reg), __ T$3$5, - as_FloatRegister($src$$reg), sh); + __ usra(as_FloatRegister($dst$$reg), __ T$1$3, + as_FloatRegister($src$$reg), sh); }', ` - __ $2(as_FloatRegister($dst$$reg), __ T$3$5, + __ usra(as_FloatRegister($dst$$reg), __ T$1$3, as_FloatRegister($src$$reg), (int)$shift$$constant);') %} - ins_pipe(vshift`'ifelse($6, D, 64, 128)_imm); + ins_pipe(vshift`'ifelse($4, D, 64, 128)_imm); %}')dnl dnl define(`VSRAA_IMM', ` -instruct vsraa$3$4_imm`'(vec$6 dst, vec$6 src, immI shift) %{ - predicate(n->as_Vector()->length() == $3); - match(Set dst (AddV$4 dst (RShiftV$4 src (RShiftCntV shift)))); +instruct vsraa$1$2_imm`'(vec$4 dst, vec$4 src, immI shift) %{ + predicate(n->as_Vector()->length() == $1); + match(Set dst (AddV$2 dst (RShiftV$2 src (RShiftCntV shift)))); ins_cost(INSN_COST); - format %{ "$1 $dst, $src, $shift\t# vector ($3$5)" %} - ins_encode %{ifelse($4, B,` + format %{ "ssra $dst, $src, $shift\t# vector ($1$3)" %} + ins_encode %{ifelse($2, B,` int sh = (int)$shift$$constant; if (sh >= 8) sh = 7; - __ $2(as_FloatRegister($dst$$reg), __ T$3$5, - as_FloatRegister($src$$reg), sh);', $4, S,` + __ ssra(as_FloatRegister($dst$$reg), __ T$1$3, + as_FloatRegister($src$$reg), sh);', $2, S,` int sh = (int)$shift$$constant; if (sh >= 16) sh = 15; - __ $2(as_FloatRegister($dst$$reg), __ T$3$5, - as_FloatRegister($src$$reg), sh);', ` - __ $2(as_FloatRegister($dst$$reg), __ T$3$5, + __ ssra(as_FloatRegister($dst$$reg), __ T$1$3, + as_FloatRegister($src$$reg), sh);', ` + __ ssra(as_FloatRegister($dst$$reg), __ T$1$3, as_FloatRegister($src$$reg), (int)$shift$$constant);') %} - ins_pipe(vshift`'ifelse($6, D, 64, 128)_imm); + ins_pipe(vshift`'ifelse($4, D, 64, 128)_imm); %}')dnl -dnl $1 $2 $3 $4 $5 $6 -VSLL(sshl, sshl, 8, B, B, D) -VSLL(sshl, sshl, 16, B, B, X) +dnl +undefine(PREDICATE)dnl +dnl +dnl $1 $2 $3 $4 +VSLL(8, B, B, D) +VSLL(16, B, B, X) // Right shifts with vector shift count on aarch64 SIMD are implemented // as left shift by negative shift count. @@ -2199,8 +2253,6 @@ VSLL(sshl, sshl, 16, B, B, X) // LoadVector RShiftCntV // | / // RShiftVI -// Note: In inner loop, multiple neg instructions are used, which can be -// moved to outer loop and merge into one neg instruction. // // Case 2: The vector shift count is from loading. // This case isn't supported by middle-end now. But it's supported by @@ -2210,61 +2262,83 @@ VSLL(sshl, sshl, 16, B, B, X) // | / // RShiftVI // -dnl $1 $2 $3 $4 $5 $6 -VSRA(negr, sshl, 8, B, B, D) -VSRA(negr, sshl, 16, B, B, X) -VSRL(negr, ushl, 8, B, B, D) -VSRL(negr, ushl, 16, B, B, X) -VSLL_IMM(shl, shl, 8, B, B, D) -VSLL_IMM(shl, shl, 16, B, B, X) -VSRA_IMM(sshr, sshr, 8, B, B, D) -VSRA_IMM(sshr, sshr, 16, B, B, X) -VSRL_IMM(ushr, ushr, 8, B, B, D) -VSRL_IMM(ushr, ushr, 16, B, B, X) -VSLL(sshl, sshl, 4, S, H, D) -VSLL(sshl, sshl, 8, S, H, X) -VSRA(negr, sshl, 4, S, H, D) -VSRA(negr, sshl, 8, S, H, X) -VSRL(negr, ushl, 4, S, H, D) -VSRL(negr, ushl, 8, S, H, X) -VSLL_IMM(shl, shl, 4, S, H, D) -VSLL_IMM(shl, shl, 8, S, H, X) -VSRA_IMM(sshr, sshr, 4, S, H, D) -VSRA_IMM(sshr, sshr, 8, S, H, X) -VSRL_IMM(ushr, ushr, 4, S, H, D) -VSRL_IMM(ushr, ushr, 8, S, H, X) -VSLL(sshl, sshl, 2, I, S, D) -VSLL(sshl, sshl, 4, I, S, X) -VSRA(negr, sshl, 2, I, S, D) -VSRA(negr, sshl, 4, I, S, X) -VSRL(negr, ushl, 2, I, S, D) -VSRL(negr, ushl, 4, I, S, X) -VSLL_IMM(shl, shl, 2, I, S, D) -VSLL_IMM(shl, shl, 4, I, S, X) -VSRA_IMM(sshr, sshr, 2, I, S, D) -VSRA_IMM(sshr, sshr, 4, I, S, X) -VSRL_IMM(ushr, ushr, 2, I, S, D) -VSRL_IMM(ushr, ushr, 4, I, S, X) -VSLL(sshl, sshl, 2, L, D, X) -VSRA(negr, sshl, 2, L, D, X) -VSRL(negr, ushl, 2, L, D, X) -VSLL_IMM(shl, shl, 2, L, D, X) -VSRA_IMM(sshr, sshr, 2, L, D, X) -VSRL_IMM(ushr, ushr, 2, L, D, X) -VSRAA_IMM(ssra, ssra, 8, B, B, D) -VSRAA_IMM(ssra, ssra, 16, B, B, X) -VSRAA_IMM(ssra, ssra, 4, S, H, D) -VSRAA_IMM(ssra, ssra, 8, S, H, X) -VSRAA_IMM(ssra, ssra, 2, I, S, D) -VSRAA_IMM(ssra, ssra, 4, I, S, X) -VSRAA_IMM(ssra, ssra, 2, L, D, X) -VSRLA_IMM(usra, usra, 8, B, B, D) -VSRLA_IMM(usra, usra, 16, B, B, X) -VSRLA_IMM(usra, usra, 4, S, H, D) -VSRLA_IMM(usra, usra, 8, S, H, X) -VSRLA_IMM(usra, usra, 2, I, S, D) -VSRLA_IMM(usra, usra, 4, I, S, X) -VSRLA_IMM(usra, usra, 2, L, D, X) +// The negate is conducted in RShiftCntV rule for case 1, whereas it's done in +// RShiftV* rules for case 2. Because there exists an optimization opportunity +// for case 1, that is, multiple neg instructions in inner loop can be hoisted +// to outer loop and merged into one neg instruction. +// +// Note that ShiftVNode::is_var_shift() indicates whether the vector shift +// count is a variable vector(case 2) or not(a vector generated by RShiftCntV, +// i.e. case 1). +dnl $1 $2 $3 $4 +VSRA(8, B, B, D) +VSRA_VAR(8, B, B, D) +VSRA(16, B, B, X) +VSRA_VAR(16, B, B, X) +VSRL(8, B, B, D) +VSRL_VAR(8, B, B, D) +VSRL(16, B, B, X) +VSRL_VAR(16, B, B, X) +VSLL_IMM(8, B, B, D) +VSLL_IMM(16, B, B, X) +VSRA_IMM(8, B, B, D) +VSRA_IMM(16, B, B, X) +VSRL_IMM(8, B, B, D) +VSRL_IMM(16, B, B, X) +VSLL(4, S, H, D) +VSLL(8, S, H, X) +VSRA(4, S, H, D) +VSRA_VAR(4, S, H, D) +VSRA(8, S, H, X) +VSRA_VAR(8, S, H, X) +VSRL(4, S, H, D) +VSRL_VAR(4, S, H, D) +VSRL(8, S, H, X) +VSRL_VAR(8, S, H, X) +VSLL_IMM(4, S, H, D) +VSLL_IMM(8, S, H, X) +VSRA_IMM(4, S, H, D) +VSRA_IMM(8, S, H, X) +VSRL_IMM(4, S, H, D) +VSRL_IMM(8, S, H, X) +VSLL(2, I, S, D) +VSLL(4, I, S, X) +VSRA(2, I, S, D) +VSRA_VAR(2, I, S, D) +VSRA(4, I, S, X) +VSRA_VAR(4, I, S, X) +VSRL(2, I, S, D) +VSRL_VAR(2, I, S, D) +VSRL(4, I, S, X) +VSRL_VAR(4, I, S, X) +VSLL_IMM(2, I, S, D) +VSLL_IMM(4, I, S, X) +VSRA_IMM(2, I, S, D) +VSRA_IMM(4, I, S, X) +VSRL_IMM(2, I, S, D) +VSRL_IMM(4, I, S, X) +VSLL(2, L, D, X) +VSRA(2, L, D, X) +VSRA_VAR(2, L, D, X) +VSRL(2, L, D, X) +VSRL_VAR(2, L, D, X) +VSLL_IMM(2, L, D, X) +VSRA_IMM(2, L, D, X) +VSRL_IMM(2, L, D, X) +VSRAA_IMM(8, B, B, D) +VSRAA_IMM(16, B, B, X) +VSRAA_IMM(4, S, H, D) +VSRAA_IMM(8, S, H, X) +VSRAA_IMM(2, I, S, D) +VSRAA_IMM(4, I, S, X) +VSRAA_IMM(2, L, D, X) +VSRLA_IMM(8, B, B, D) +VSRLA_IMM(16, B, B, X) +VSRLA_IMM(4, S, H, D) +VSRLA_IMM(8, S, H, X) +VSRLA_IMM(2, I, S, D) +VSRLA_IMM(4, I, S, X) +VSRLA_IMM(2, L, D, X) dnl define(`VMINMAX', ` instruct v$1$3`'ifelse($5, S, F, D)`'(vec$6 dst, vec$6 src1, vec$6 src2) diff --git a/src/hotspot/cpu/aarch64/assembler_aarch64.hpp b/src/hotspot/cpu/aarch64/assembler_aarch64.hpp index 9482c3a65c2ec25c6aca521798e8c9f2204a393a..10fcdaa243c006afdb3e5ebc9e21a51f6970c2b4 100644 --- a/src/hotspot/cpu/aarch64/assembler_aarch64.hpp +++ b/src/hotspot/cpu/aarch64/assembler_aarch64.hpp @@ -987,33 +987,35 @@ public: rf(rt, 0); } - void hint(int imm) { - system(0b00, 0b011, 0b0010, 0b0000, imm); - } - - void nop() { - hint(0); - } - - void yield() { - hint(1); - } + // Hint instructions - void wfe() { - hint(2); +#define INSN(NAME, crm, op2) \ + void NAME() { \ + system(0b00, 0b011, 0b0010, crm, op2); \ } - void wfi() { - hint(3); - } + INSN(nop, 0b000, 0b0000); + INSN(yield, 0b000, 0b0001); + INSN(wfe, 0b000, 0b0010); + INSN(wfi, 0b000, 0b0011); + INSN(sev, 0b000, 0b0100); + INSN(sevl, 0b000, 0b0101); - void sev() { - hint(4); - } + INSN(autia1716, 0b0001, 0b100); + INSN(autiasp, 0b0011, 0b101); + INSN(autiaz, 0b0011, 0b100); + INSN(autib1716, 0b0001, 0b110); + INSN(autibsp, 0b0011, 0b111); + INSN(autibz, 0b0011, 0b110); + INSN(pacia1716, 0b0001, 0b000); + INSN(paciasp, 0b0011, 0b001); + INSN(paciaz, 0b0011, 0b000); + INSN(pacib1716, 0b0001, 0b010); + INSN(pacibsp, 0b0011, 0b011); + INSN(pacibz, 0b0011, 0b010); + INSN(xpaclri, 0b0000, 0b111); - void sevl() { - hint(5); - } +#undef INSN // we only provide mrs and msr for the special purpose system // registers where op1 (instr[20:19]) == 11 and, (currently) only @@ -1099,18 +1101,21 @@ public: } // Unconditional branch (register) - void branch_reg(Register R, int opc) { + + void branch_reg(int OP, int A, int M, Register RN, Register RM) { starti; f(0b1101011, 31, 25); - f(opc, 24, 21); - f(0b11111000000, 20, 10); - rf(R, 5); - f(0b00000, 4, 0); + f(OP, 24, 21); + f(0b111110000, 20, 12); + f(A, 11, 11); + f(M, 10, 10); + rf(RN, 5); + rf(RM, 0); } -#define INSN(NAME, opc) \ - void NAME(Register R) { \ - branch_reg(R, opc); \ +#define INSN(NAME, opc) \ + void NAME(Register RN) { \ + branch_reg(opc, 0, 0, RN, r0); \ } INSN(br, 0b0000); @@ -1121,14 +1126,48 @@ public: #undef INSN -#define INSN(NAME, opc) \ - void NAME() { \ - branch_reg(dummy_reg, opc); \ +#define INSN(NAME, opc) \ + void NAME() { \ + branch_reg(opc, 0, 0, dummy_reg, r0); \ } INSN(eret, 0b0100); INSN(drps, 0b0101); +#undef INSN + +#define INSN(NAME, M) \ + void NAME() { \ + branch_reg(0b0010, 1, M, dummy_reg, dummy_reg); \ + } + + INSN(retaa, 0); + INSN(retab, 1); + +#undef INSN + +#define INSN(NAME, OP, M) \ + void NAME(Register rn) { \ + branch_reg(OP, 1, M, rn, dummy_reg); \ + } + + INSN(braaz, 0b0000, 0); + INSN(brabz, 0b0000, 1); + INSN(blraaz, 0b0001, 0); + INSN(blrabz, 0b0001, 1); + +#undef INSN + +#define INSN(NAME, OP, M) \ + void NAME(Register rn, Register rm) { \ + branch_reg(OP, 1, M, rn, rm); \ + } + + INSN(braa, 0b1000, 0); + INSN(brab, 0b1000, 1); + INSN(blraa, 0b1001, 0); + INSN(blrab, 0b1001, 1); + #undef INSN // Load/store exclusive @@ -1792,6 +1831,37 @@ void mvnw(Register Rd, Register Rm, INSN(clz, 0b110, 0b00000, 0b00100); INSN(cls, 0b110, 0b00000, 0b00101); + // PAC instructions + INSN(pacia, 0b110, 0b00001, 0b00000); + INSN(pacib, 0b110, 0b00001, 0b00001); + INSN(pacda, 0b110, 0b00001, 0b00010); + INSN(pacdb, 0b110, 0b00001, 0b00011); + INSN(autia, 0b110, 0b00001, 0b00100); + INSN(autib, 0b110, 0b00001, 0b00101); + INSN(autda, 0b110, 0b00001, 0b00110); + INSN(autdb, 0b110, 0b00001, 0b00111); + +#undef INSN + +#define INSN(NAME, op29, opcode2, opcode) \ + void NAME(Register Rd) { \ + starti; \ + f(opcode2, 20, 16); \ + data_processing(current_insn, op29, opcode, Rd, dummy_reg); \ + } + + // PAC instructions (with zero modifier) + INSN(paciza, 0b110, 0b00001, 0b01000); + INSN(pacizb, 0b110, 0b00001, 0b01001); + INSN(pacdza, 0b110, 0b00001, 0b01010); + INSN(pacdzb, 0b110, 0b00001, 0b01011); + INSN(autiza, 0b110, 0b00001, 0b01100); + INSN(autizb, 0b110, 0b00001, 0b01101); + INSN(autdza, 0b110, 0b00001, 0b01110); + INSN(autdzb, 0b110, 0b00001, 0b01111); + INSN(xpaci, 0b110, 0b00001, 0b10000); + INSN(xpacd, 0b110, 0b00001, 0b10001); + #undef INSN // (2 sources) diff --git a/src/hotspot/cpu/aarch64/c1_Runtime1_aarch64.cpp b/src/hotspot/cpu/aarch64/c1_Runtime1_aarch64.cpp index 005f739f0aa0566a83bda8adff7d2cc0106ff3b7..342aa87a6208d9b3059be01e910635f8ada97509 100644 --- a/src/hotspot/cpu/aarch64/c1_Runtime1_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/c1_Runtime1_aarch64.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2022, 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. * @@ -385,6 +385,7 @@ OopMapSet* Runtime1::generate_handle_exception(StubID id, StubAssembler *sasm) { // load issuing PC (the return address for this stub) into r3 __ ldr(exception_pc, Address(rfp, 1*BytesPerWord)); + __ authenticate_return_address(exception_pc, rscratch1); // make sure that the vm_results are cleared (may be unnecessary) __ str(zr, Address(rthread, JavaThread::vm_result_offset())); @@ -433,6 +434,7 @@ OopMapSet* Runtime1::generate_handle_exception(StubID id, StubAssembler *sasm) { __ str(exception_pc, Address(rthread, JavaThread::exception_pc_offset())); // patch throwing pc into return address (has bci & oop map) + __ protect_return_address(exception_pc, rscratch1); __ str(exception_pc, Address(rfp, 1*BytesPerWord)); // compute the exception handler. @@ -448,6 +450,7 @@ OopMapSet* Runtime1::generate_handle_exception(StubID id, StubAssembler *sasm) { __ invalidate_registers(false, true, true, true, true, true); // patch the return address, this stub will directly return to the exception handler + __ protect_return_address(r0, rscratch1); __ str(r0, Address(rfp, 1*BytesPerWord)); switch (id) { @@ -496,10 +499,12 @@ void Runtime1::generate_unwind_exception(StubAssembler *sasm) { // Save our return address because // exception_handler_for_return_address will destroy it. We also // save exception_oop + __ mov(r3, lr); + __ protect_return_address(); __ stp(lr, exception_oop, Address(__ pre(sp, -2 * wordSize))); // search the exception handler address of the caller (using the return address) - __ call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::exception_handler_for_return_address), rthread, lr); + __ call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::exception_handler_for_return_address), rthread, r3); // r0: exception handler address of the caller // Only R0 is valid at this time; all other registers have been @@ -512,6 +517,7 @@ void Runtime1::generate_unwind_exception(StubAssembler *sasm) { // get throwing pc (= return address). // lr has been destroyed by the call __ ldp(lr, exception_oop, Address(__ post(sp, 2 * wordSize))); + __ authenticate_return_address(); __ mov(r3, lr); __ verify_not_null_oop(exception_oop); diff --git a/src/hotspot/cpu/aarch64/frame_aarch64.cpp b/src/hotspot/cpu/aarch64/frame_aarch64.cpp index cb59e8b12afc79f32b5e3793d216ed49b4beb000..3363e53690e474bf5dbde3ef92c4f87601b96e08 100644 --- a/src/hotspot/cpu/aarch64/frame_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/frame_aarch64.cpp @@ -128,13 +128,13 @@ bool frame::safe_for_sender(JavaThread *thread) { return false; } - sender_pc = (address) this->fp()[return_addr_offset]; // for interpreted frames, the value below is the sender "raw" sp, // which can be different from the sender unextended sp (the sp seen // by the sender) because of current frame local variables sender_sp = (intptr_t*) addr_at(sender_sp_offset); sender_unextended_sp = (intptr_t*) this->fp()[interpreter_frame_sender_sp_offset]; saved_fp = (intptr_t*) this->fp()[link_offset]; + sender_pc = pauth_strip_verifiable((address) this->fp()[return_addr_offset], (address)saved_fp); } else { // must be some sort of compiled/runtime frame @@ -151,9 +151,9 @@ bool frame::safe_for_sender(JavaThread *thread) { return false; } sender_unextended_sp = sender_sp; - sender_pc = (address) *(sender_sp-1); // Note: frame::sender_sp_offset is only valid for compiled frame saved_fp = (intptr_t*) *(sender_sp - frame::sender_sp_offset); + sender_pc = pauth_strip_verifiable((address) *(sender_sp-1), (address)saved_fp); } @@ -268,17 +268,22 @@ bool frame::safe_for_sender(JavaThread *thread) { void frame::patch_pc(Thread* thread, address pc) { assert(_cb == CodeCache::find_blob(pc), "unexpected pc"); address* pc_addr = &(((address*) sp())[-1]); + address signing_sp = (((address*) sp())[-2]); + address signed_pc = pauth_sign_return_address(pc, (address)signing_sp); + address pc_old = pauth_strip_verifiable(*pc_addr, (address)signing_sp); if (TracePcPatching) { - tty->print_cr("patch_pc at address " INTPTR_FORMAT " [" INTPTR_FORMAT " -> " INTPTR_FORMAT "]", - p2i(pc_addr), p2i(*pc_addr), p2i(pc)); + tty->print("patch_pc at address " INTPTR_FORMAT " [" INTPTR_FORMAT " -> " INTPTR_FORMAT "]", + p2i(pc_addr), p2i(pc_old), p2i(pc)); + if (VM_Version::use_rop_protection()) { + tty->print(" [signed " INTPTR_FORMAT " -> " INTPTR_FORMAT "]", p2i(*pc_addr), p2i(signed_pc)); + } + tty->print_cr(""); } - // Only generated code frames should be patched, therefore the return address will not be signed. - assert(pauth_ptr_is_raw(*pc_addr), "cannot be signed"); // Either the return address is the original one or we are going to // patch in the same address that's already there. - assert(_pc == *pc_addr || pc == *pc_addr, "must be"); - *pc_addr = pc; + assert(_pc == pc_old || pc == pc_old, "must be"); + *pc_addr = signed_pc; address original_pc = CompiledMethod::get_deopt_original_pc(this); if (original_pc != NULL) { assert(original_pc == _pc, "expected original PC to be stored before patching"); @@ -455,12 +460,12 @@ frame frame::sender_for_interpreter_frame(RegisterMap* map) const { } #endif // COMPILER2_OR_JVMCI - // Use the raw version of pc - the interpreter should not have signed it. + // For ROP protection, Interpreter will have signed the sender_pc, but there is no requirement to authenticate it here. + address sender_pc = pauth_strip_verifiable(sender_pc_maybe_signed(), (address)link()); - return frame(sender_sp, unextended_sp, link(), sender_pc_maybe_signed()); + return frame(sender_sp, unextended_sp, link(), sender_pc); } - //------------------------------------------------------------------------------ // frame::sender_for_compiled_frame frame frame::sender_for_compiled_frame(RegisterMap* map) const { @@ -482,7 +487,9 @@ frame frame::sender_for_compiled_frame(RegisterMap* map) const { intptr_t* unextended_sp = l_sender_sp; // the return_address is always the word on the stack - address sender_pc = (address) *(l_sender_sp-1); + + // For ROP protection, C1/C2 will have signed the sender_pc, but there is no requirement to authenticate it here. + address sender_pc = pauth_strip_verifiable((address) *(l_sender_sp-1), (address) *(l_sender_sp-2)); intptr_t** saved_fp_addr = (intptr_t**) (l_sender_sp - frame::sender_sp_offset); @@ -530,6 +537,9 @@ frame frame::sender_raw(RegisterMap* map) const { // Must be native-compiled frame, i.e. the marshaling code for native // methods that exists in the core system. + // Native code may or may not have signed the return address, we have no way to be sure or what + // signing methods they used. Instead, just ensure the stripped value is used. + return frame(sender_sp(), link(), sender_pc()); } diff --git a/src/hotspot/cpu/aarch64/frame_aarch64.inline.hpp b/src/hotspot/cpu/aarch64/frame_aarch64.inline.hpp index b0fe436ca59609a5475c4503b755675a0c55bd58..20b5b8e8662484d0f3319416f3ce79f373b6f959 100644 --- a/src/hotspot/cpu/aarch64/frame_aarch64.inline.hpp +++ b/src/hotspot/cpu/aarch64/frame_aarch64.inline.hpp @@ -148,10 +148,12 @@ inline intptr_t* frame::id(void) const { return unextended_sp(); } inline bool frame::is_older(intptr_t* id) const { assert(this->id() != NULL && id != NULL, "NULL frame id"); return this->id() > id ; } - - inline intptr_t* frame::link() const { return (intptr_t*) *(intptr_t **)addr_at(link_offset); } +inline intptr_t* frame::link_or_null() const { + intptr_t** ptr = (intptr_t **)addr_at(link_offset); + return os::is_readable_pointer(ptr) ? *ptr : NULL; +} inline intptr_t* frame::unextended_sp() const { return _unextended_sp; } diff --git a/src/hotspot/cpu/aarch64/gc/g1/g1BarrierSetAssembler_aarch64.cpp b/src/hotspot/cpu/aarch64/gc/g1/g1BarrierSetAssembler_aarch64.cpp index cd689b008e05ee143542d98e48c225600785892b..01aff54c96d5582e65dec49346fc993b507d2abd 100644 --- a/src/hotspot/cpu/aarch64/gc/g1/g1BarrierSetAssembler_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/gc/g1/g1BarrierSetAssembler_aarch64.cpp @@ -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 @@ -271,7 +271,7 @@ void G1BarrierSetAssembler::load_at(MacroAssembler* masm, DecoratorSet decorator ModRefBarrierSetAssembler::load_at(masm, decorators, type, dst, src, tmp1, tmp_thread); if (on_oop && on_reference) { // LR is live. It must be saved around calls. - __ enter(); // barrier may call runtime + __ enter(/*strip_ret_addr*/true); // barrier may call runtime // Generate the G1 pre-barrier code to log the value of // the referent field in an SATB buffer. g1_write_barrier_pre(masm /* masm */, diff --git a/src/hotspot/cpu/aarch64/gc/shenandoah/shenandoahBarrierSetAssembler_aarch64.cpp b/src/hotspot/cpu/aarch64/gc/shenandoah/shenandoahBarrierSetAssembler_aarch64.cpp index 53de1d921fca33dc4213bbdfb1574c48d9a901eb..bcabb40e63cbea92dfe2ec363c7206908ce7c2a6 100644 --- a/src/hotspot/cpu/aarch64/gc/shenandoah/shenandoahBarrierSetAssembler_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/gc/shenandoah/shenandoahBarrierSetAssembler_aarch64.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 @@ -237,7 +237,7 @@ void ShenandoahBarrierSetAssembler::load_reference_barrier(MacroAssembler* masm, bool is_narrow = UseCompressedOops && !is_native; Label heap_stable, not_cset; - __ enter(); + __ enter(/*strip_ret_addr*/true); Address gc_state(rthread, in_bytes(ShenandoahThreadLocalData::gc_state_offset())); __ ldrb(rscratch2, gc_state); @@ -359,7 +359,7 @@ void ShenandoahBarrierSetAssembler::load_at(MacroAssembler* masm, DecoratorSet d // 3: apply keep-alive barrier if needed if (ShenandoahBarrierSet::need_keep_alive_barrier(decorators, type)) { - __ enter(); + __ enter(/*strip_ret_addr*/true); __ push_call_clobbered_registers(); satb_write_barrier_pre(masm /* masm */, noreg /* obj */, diff --git a/src/hotspot/cpu/aarch64/gc/z/zBarrierSetAssembler_aarch64.cpp b/src/hotspot/cpu/aarch64/gc/z/zBarrierSetAssembler_aarch64.cpp index 10b1cf20ef910240b4988db7d611a1b778d71ca4..6820be15950ec50f975ee6c870b52c2024317882 100644 --- a/src/hotspot/cpu/aarch64/gc/z/zBarrierSetAssembler_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/gc/z/zBarrierSetAssembler_aarch64.cpp @@ -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 @@ -78,7 +78,7 @@ void ZBarrierSetAssembler::load_at(MacroAssembler* masm, __ tst(dst, rscratch1); __ br(Assembler::EQ, done); - __ enter(); + __ enter(/*strip_ret_addr*/true); __ push_call_clobbered_registers_except(RegSet::of(dst)); diff --git a/src/hotspot/cpu/aarch64/globals_aarch64.hpp b/src/hotspot/cpu/aarch64/globals_aarch64.hpp index 82760cc3bcf066becfedc9c5fb279c2a14cd1c89..443eb46b720ab97ad5381f40c8fffa701ddd6f53 100644 --- a/src/hotspot/cpu/aarch64/globals_aarch64.hpp +++ b/src/hotspot/cpu/aarch64/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) 2015, 2019, Red Hat Inc. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -118,7 +118,9 @@ define_pd_global(intx, InlineSmallCode, 1000); product(uint, OnSpinWaitInstCount, 1, DIAGNOSTIC, \ "The number of OnSpinWaitInst instructions to generate." \ "It cannot be used with OnSpinWaitInst=none.") \ - range(1, 99) + range(1, 99) \ + product(ccstr, UseBranchProtection, "none", \ + "Branch Protection to use: none, standard, pac-ret") \ // end of ARCH_FLAGS diff --git a/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp b/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp index 69124c299c15145aef0debd8e49596f396dd35d6..ad1a6d58596ff0e08ca6f1f9b188007fad252227 100644 --- a/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp @@ -1137,6 +1137,8 @@ void MacroAssembler::verify_oop(Register reg, const char* s) { } BLOCK_COMMENT("verify_oop {"); + strip_return_address(); // This might happen within a stack frame. + protect_return_address(); stp(r0, rscratch1, Address(pre(sp, -2 * wordSize))); stp(rscratch2, lr, Address(pre(sp, -2 * wordSize))); @@ -1150,6 +1152,7 @@ void MacroAssembler::verify_oop(Register reg, const char* s) { ldp(rscratch2, lr, Address(post(sp, 2 * wordSize))); ldp(r0, rscratch1, Address(post(sp, 2 * wordSize))); + authenticate_return_address(); BLOCK_COMMENT("} verify_oop"); } @@ -1166,6 +1169,8 @@ void MacroAssembler::verify_oop_addr(Address addr, const char* s) { } BLOCK_COMMENT("verify_oop_addr {"); + strip_return_address(); // This might happen within a stack frame. + protect_return_address(); stp(r0, rscratch1, Address(pre(sp, -2 * wordSize))); stp(rscratch2, lr, Address(pre(sp, -2 * wordSize))); @@ -1186,6 +1191,7 @@ void MacroAssembler::verify_oop_addr(Address addr, const char* s) { ldp(rscratch2, lr, Address(post(sp, 2 * wordSize))); ldp(r0, rscratch1, Address(post(sp, 2 * wordSize))); + authenticate_return_address(); BLOCK_COMMENT("} verify_oop_addr"); } @@ -2537,7 +2543,7 @@ void MacroAssembler::debug64(char* msg, int64_t pc, int64_t regs[]) fatal("DEBUG MESSAGE: %s", msg); } -RegSet MacroAssembler::call_clobbered_registers() { +RegSet MacroAssembler::call_clobbered_gp_registers() { RegSet regs = RegSet::range(r0, r17) - RegSet::of(rscratch1, rscratch2); #ifndef R18_RESERVED regs += r18_tls; @@ -2547,7 +2553,7 @@ RegSet MacroAssembler::call_clobbered_registers() { void MacroAssembler::push_call_clobbered_registers_except(RegSet exclude) { int step = 4 * wordSize; - push(call_clobbered_registers() - exclude, sp); + push(call_clobbered_gp_registers() - exclude, sp); sub(sp, sp, step); mov(rscratch1, -step); // Push v0-v7, v16-v31. @@ -2569,7 +2575,7 @@ void MacroAssembler::pop_call_clobbered_registers_except(RegSet exclude) { reinitialize_ptrue(); - pop(call_clobbered_registers() - exclude, sp); + pop(call_clobbered_gp_registers() - exclude, sp); } void MacroAssembler::push_CPU_state(bool save_vectors, bool use_sve, @@ -4296,6 +4302,7 @@ void MacroAssembler::load_byte_map_base(Register reg) { void MacroAssembler::build_frame(int framesize) { assert(framesize >= 2 * wordSize, "framesize must include space for FP/LR"); assert(framesize % (2*wordSize) == 0, "must preserve 2*wordSize alignment"); + protect_return_address(); if (framesize < ((1 << 9) + 2 * wordSize)) { sub(sp, sp, framesize); stp(rfp, lr, Address(sp, framesize - 2 * wordSize)); @@ -4328,19 +4335,21 @@ void MacroAssembler::remove_frame(int framesize) { } ldp(rfp, lr, Address(post(sp, 2 * wordSize))); } + authenticate_return_address(); } -// This method checks if provided byte array contains byte with highest bit set. -address MacroAssembler::has_negatives(Register ary1, Register len, Register result) { +// This method counts leading positive bytes (highest bit not set) in provided byte array +address MacroAssembler::count_positives(Register ary1, Register len, Register result) { // Simple and most common case of aligned small array which is not at the // end of memory page is placed here. All other cases are in stub. Label LOOP, END, STUB, STUB_LONG, SET_RESULT, DONE; const uint64_t UPPER_BIT_MASK=0x8080808080808080; assert_different_registers(ary1, len, result); + mov(result, len); cmpw(len, 0); - br(LE, SET_RESULT); + br(LE, DONE); cmpw(len, 4 * wordSize); br(GE, STUB_LONG); // size > 32 then go to stub @@ -4359,19 +4368,20 @@ address MacroAssembler::has_negatives(Register ary1, Register len, Register resu subs(len, len, wordSize); br(GE, LOOP); cmpw(len, -wordSize); - br(EQ, SET_RESULT); + br(EQ, DONE); BIND(END); - ldr(result, Address(ary1)); - sub(len, zr, len, LSL, 3); // LSL 3 is to get bits from bytes - lslv(result, result, len); - tst(result, UPPER_BIT_MASK); - b(SET_RESULT); + ldr(rscratch1, Address(ary1)); + sub(rscratch2, zr, len, LSL, 3); // LSL 3 is to get bits from bytes + lslv(rscratch1, rscratch1, rscratch2); + tst(rscratch1, UPPER_BIT_MASK); + br(NE, SET_RESULT); + b(DONE); BIND(STUB); - RuntimeAddress has_neg = RuntimeAddress(StubRoutines::aarch64::has_negatives()); - assert(has_neg.target() != NULL, "has_negatives stub has not been generated"); - address tpc1 = trampoline_call(has_neg); + RuntimeAddress count_pos = RuntimeAddress(StubRoutines::aarch64::count_positives()); + assert(count_pos.target() != NULL, "count_positives stub has not been generated"); + address tpc1 = trampoline_call(count_pos); if (tpc1 == NULL) { DEBUG_ONLY(reset_labels(STUB_LONG, SET_RESULT, DONE)); postcond(pc() == badAddress); @@ -4380,9 +4390,9 @@ address MacroAssembler::has_negatives(Register ary1, Register len, Register resu b(DONE); BIND(STUB_LONG); - RuntimeAddress has_neg_long = RuntimeAddress(StubRoutines::aarch64::has_negatives_long()); - assert(has_neg_long.target() != NULL, "has_negatives stub has not been generated"); - address tpc2 = trampoline_call(has_neg_long); + RuntimeAddress count_pos_long = RuntimeAddress(StubRoutines::aarch64::count_positives_long()); + assert(count_pos_long.target() != NULL, "count_positives_long stub has not been generated"); + address tpc2 = trampoline_call(count_pos_long); if (tpc2 == NULL) { DEBUG_ONLY(reset_labels(SET_RESULT, DONE)); postcond(pc() == badAddress); @@ -4391,7 +4401,9 @@ address MacroAssembler::has_negatives(Register ary1, Register len, Register resu b(DONE); BIND(SET_RESULT); - cset(result, NE); // set true or false + + add(len, len, wordSize); + sub(result, result, len); BIND(DONE); postcond(pc() != badAddress); @@ -5169,6 +5181,7 @@ void MacroAssembler::get_thread(Register dst) { LINUX_ONLY(RegSet::range(r0, r1) + lr - dst) NOT_LINUX (RegSet::range(r0, r17) + lr - dst); + protect_return_address(); push(saved_regs, sp); mov(lr, CAST_FROM_FN_PTR(address, JavaThread::aarch64_get_thread_helper)); @@ -5178,6 +5191,7 @@ void MacroAssembler::get_thread(Register dst) { } pop(saved_regs, sp); + authenticate_return_address(); } void MacroAssembler::cache_wb(Address line) { @@ -5269,3 +5283,102 @@ void MacroAssembler::spin_wait() { } } } + +// Stack frame creation/removal + +void MacroAssembler::enter(bool strip_ret_addr) { + if (strip_ret_addr) { + // Addresses can only be signed once. If there are multiple nested frames being created + // in the same function, then the return address needs stripping first. + strip_return_address(); + } + protect_return_address(); + stp(rfp, lr, Address(pre(sp, -2 * wordSize))); + mov(rfp, sp); +} + +void MacroAssembler::leave() { + mov(sp, rfp); + ldp(rfp, lr, Address(post(sp, 2 * wordSize))); + authenticate_return_address(); +} + +// ROP Protection +// Use the AArch64 PAC feature to add ROP protection for generated code. Use whenever creating/ +// destroying stack frames or whenever directly loading/storing the LR to memory. +// If ROP protection is not set then these functions are no-ops. +// For more details on PAC see pauth_aarch64.hpp. + +// Sign the LR. Use during construction of a stack frame, before storing the LR to memory. +// Uses the FP as the modifier. +// +void MacroAssembler::protect_return_address() { + if (VM_Version::use_rop_protection()) { + check_return_address(); + // The standard convention for C code is to use paciasp, which uses SP as the modifier. This + // works because in C code, FP and SP match on function entry. In the JDK, SP and FP may not + // match, so instead explicitly use the FP. + pacia(lr, rfp); + } +} + +// Sign the return value in the given register. Use before updating the LR in the exisiting stack +// frame for the current function. +// Uses the FP from the start of the function as the modifier - which is stored at the address of +// the current FP. +// +void MacroAssembler::protect_return_address(Register return_reg, Register temp_reg) { + if (VM_Version::use_rop_protection()) { + assert(PreserveFramePointer, "PreserveFramePointer must be set for ROP protection"); + check_return_address(return_reg); + ldr(temp_reg, Address(rfp)); + pacia(return_reg, temp_reg); + } +} + +// Authenticate the LR. Use before function return, after restoring FP and loading LR from memory. +// +void MacroAssembler::authenticate_return_address(Register return_reg) { + if (VM_Version::use_rop_protection()) { + autia(return_reg, rfp); + check_return_address(return_reg); + } +} + +// Authenticate the return value in the given register. Use before updating the LR in the exisiting +// stack frame for the current function. +// Uses the FP from the start of the function as the modifier - which is stored at the address of +// the current FP. +// +void MacroAssembler::authenticate_return_address(Register return_reg, Register temp_reg) { + if (VM_Version::use_rop_protection()) { + assert(PreserveFramePointer, "PreserveFramePointer must be set for ROP protection"); + ldr(temp_reg, Address(rfp)); + autia(return_reg, temp_reg); + check_return_address(return_reg); + } +} + +// Strip any PAC data from LR without performing any authentication. Use with caution - only if +// there is no guaranteed way of authenticating the LR. +// +void MacroAssembler::strip_return_address() { + if (VM_Version::use_rop_protection()) { + xpaclri(); + } +} + +#ifndef PRODUCT +// PAC failures can be difficult to debug. After an authentication failure, a segfault will only +// occur when the pointer is used - ie when the program returns to the invalid LR. At this point +// it is difficult to debug back to the callee function. +// This function simply loads from the address in the given register. +// Use directly after authentication to catch authentication failures. +// Also use before signing to check that the pointer is valid and hasn't already been signed. +// +void MacroAssembler::check_return_address(Register return_reg) { + if (VM_Version::use_rop_protection()) { + ldr(zr, Address(return_reg)); + } +} +#endif diff --git a/src/hotspot/cpu/aarch64/macroAssembler_aarch64.hpp b/src/hotspot/cpu/aarch64/macroAssembler_aarch64.hpp index 16f9790bde42c20cb808f6c2321b7135c1279452..d5bfc42e784d43070918d936f30c042d2b259a19 100644 --- a/src/hotspot/cpu/aarch64/macroAssembler_aarch64.hpp +++ b/src/hotspot/cpu/aarch64/macroAssembler_aarch64.hpp @@ -468,7 +468,7 @@ public: void push_fp(FloatRegSet regs, Register stack) { if (regs.bits()) push_fp(regs.bits(), stack); } void pop_fp(FloatRegSet regs, Register stack) { if (regs.bits()) pop_fp(regs.bits(), stack); } - static RegSet call_clobbered_registers(); + static RegSet call_clobbered_gp_registers(); void push_p(PRegSet regs, Register stack) { if (regs.bits()) push_p(regs.bits(), stack); } void pop_p(PRegSet regs, Register stack) { if (regs.bits()) pop_p(regs.bits(), stack); } @@ -688,16 +688,16 @@ public: void align(int modulus); // Stack frame creation/removal - void enter() - { - stp(rfp, lr, Address(pre(sp, -2 * wordSize))); - mov(rfp, sp); - } - void leave() - { - mov(sp, rfp); - ldp(rfp, lr, Address(post(sp, 2 * wordSize))); - } + void enter(bool strip_ret_addr = false); + void leave(); + + // ROP Protection + void protect_return_address(); + void protect_return_address(Register return_reg, Register temp_reg); + void authenticate_return_address(Register return_reg = lr); + void authenticate_return_address(Register return_reg, Register temp_reg); + void strip_return_address(); + void check_return_address(Register return_reg=lr) PRODUCT_RETURN; // Support for getting the JavaThread pointer (i.e.; a reference to thread-local information) // The pointer will be loaded into the thread register. @@ -1234,7 +1234,7 @@ public: Register table0, Register table1, Register table2, Register table3, bool upper = false); - address has_negatives(Register ary1, Register len, Register result); + address count_positives(Register ary1, Register len, Register result); address arrays_equals(Register a1, Register a2, Register result, Register cnt1, Register tmp1, Register tmp2, Register tmp3, int elem_size); diff --git a/src/hotspot/cpu/aarch64/matcher_aarch64.hpp b/src/hotspot/cpu/aarch64/matcher_aarch64.hpp index aca82240a5731fb10d8734bbce8411763b8744de..c2f801f408ade3700e79d217b418504a08d5fb7e 100644 --- a/src/hotspot/cpu/aarch64/matcher_aarch64.hpp +++ b/src/hotspot/cpu/aarch64/matcher_aarch64.hpp @@ -163,4 +163,10 @@ // Implements a variant of EncodeISOArrayNode that encode ASCII only static const bool supports_encode_ascii_array = true; + // Returns pre-selection estimated size of a vector operation. + static int vector_op_pre_select_sz_estimate(int vopc, BasicType ety, int vlen) { + return 0; + } + + #endif // CPU_AARCH64_MATCHER_AARCH64_HPP diff --git a/src/hotspot/cpu/aarch64/pauth_aarch64.hpp b/src/hotspot/cpu/aarch64/pauth_aarch64.hpp index e12a671daf1e2552cab87b3ac3344bb9a5d61b65..fe5fbbce9f05f22aea98bfee586123c113764023 100644 --- a/src/hotspot/cpu/aarch64/pauth_aarch64.hpp +++ b/src/hotspot/cpu/aarch64/pauth_aarch64.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, Arm Limited. All rights reserved. + * Copyright (c) 2021, 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 @@ -27,9 +27,58 @@ #include OS_CPU_HEADER_INLINE(pauth) +// Support for ROP Protection in VM code. +// This is provided via the AArch64 PAC feature. +// For more details on PAC see The Arm ARM, section "Pointer authentication in AArch64 state". +// +// PAC provides a method to sign and authenticate pointer values. Signing combines the register +// being signed, an additional modifier and a per-process secret key, writing the result to unused +// high bits of the signed register. Once signed a register must be authenticated or stripped +// before it can be used. +// Authentication reverses the signing operation, clearing the high bits. If the signed register +// or modifier has changed then authentication will fail and invalid data will be written to the +// high bits and the next time the pointer is used a segfault will be raised. +// +// Assume a malicious attacker is able to edit the stack via an exploit. Control flow can be +// changed by re-writing the return values stored on the stack. ROP protection prevents this by +// signing return addresses before saving them on the stack, then authenticating when they are +// loaded back. The scope of this protection is per function (a value is signed and authenticated +// by the same function), therefore it is possible for different functions within the same +// program to use different signing methods. +// +// The VM and native code is protected by compiling with the GCC AArch64 branch protection flag. +// +// All generated code is protected via the ROP functions provided in macroAssembler. +// +// In addition, the VM needs to be aware of PAC whenever viewing or editing the stack. Functions +// are provided here and in the OS specific files. We should assume all stack frames for generated +// code have signed return values. Rewriting the stack should ensure new values are correctly +// signed. However, we cannot make any assumptions about how (or if) native code uses PAC - here +// we should limit access to viewing via stripping. +// + + +// Confirm the given pointer has not been signed - ie none of the high bits are set. +// +// Note this can give false positives. The PAC signing can generate a signature with all signing +// bits as zeros, causing this function to return true. Therefore this should only be used for +// assert style checking. In addition, this function should never be used with a "not" to confirm +// a pointer is signed, as it will fail the above case. The only safe way to do this is to instead +// authenticate the pointer. +// inline bool pauth_ptr_is_raw(address ptr) { - // Confirm none of the high bits are set in the pointer. return ptr == pauth_strip_pointer(ptr); } +// Strip a return value (same as pauth_strip_pointer). When debug is enabled then authenticate +// instead. +// +inline address pauth_strip_verifiable(address ret_addr, address modifier) { + if (VM_Version::use_rop_protection()) { + DEBUG_ONLY(ret_addr = pauth_authenticate_return_address(ret_addr, modifier);) + NOT_DEBUG(ret_addr = pauth_strip_pointer(ret_addr)); + } + return ret_addr; +} + #endif // CPU_AARCH64_PAUTH_AARCH64_HPP diff --git a/src/hotspot/cpu/aarch64/register_aarch64.hpp b/src/hotspot/cpu/aarch64/register_aarch64.hpp index 400eaeb90f20f8c4b121317329f2e4662e19325b..3fe2fae42a16c3ac24c8f320c45a5029f10854f2 100644 --- a/src/hotspot/cpu/aarch64/register_aarch64.hpp +++ b/src/hotspot/cpu/aarch64/register_aarch64.hpp @@ -314,115 +314,10 @@ class ConcreteRegisterImpl : public AbstractRegisterImpl { static const int max_pr; }; -template class RegSetIterator; - -// A set of registers -template -class AbstractRegSet { - uint32_t _bitset; - - AbstractRegSet(uint32_t bitset) : _bitset(bitset) { } - -public: - - AbstractRegSet() : _bitset(0) { } - - AbstractRegSet(RegImpl r1) : _bitset(1 << r1->encoding()) { } - - AbstractRegSet operator+(const AbstractRegSet aSet) const { - AbstractRegSet result(_bitset | aSet._bitset); - return result; - } - - AbstractRegSet operator-(const AbstractRegSet aSet) const { - AbstractRegSet result(_bitset & ~aSet._bitset); - return result; - } - - AbstractRegSet &operator+=(const AbstractRegSet aSet) { - *this = *this + aSet; - return *this; - } - - AbstractRegSet &operator-=(const AbstractRegSet aSet) { - *this = *this - aSet; - return *this; - } - - static AbstractRegSet of(RegImpl r1) { - return AbstractRegSet(r1); - } - - static AbstractRegSet of(RegImpl r1, RegImpl r2) { - return of(r1) + r2; - } - - static AbstractRegSet of(RegImpl r1, RegImpl r2, RegImpl r3) { - return of(r1, r2) + r3; - } - - static AbstractRegSet of(RegImpl r1, RegImpl r2, RegImpl r3, RegImpl r4) { - return of(r1, r2, r3) + r4; - } - - static AbstractRegSet range(RegImpl start, RegImpl end) { - uint32_t bits = ~0; - bits <<= start->encoding(); - bits <<= 31 - end->encoding(); - bits >>= 31 - end->encoding(); - - return AbstractRegSet(bits); - } - - uint32_t bits() const { return _bitset; } - -private: - - RegImpl first(); - -public: - - friend class RegSetIterator; - - RegSetIterator begin(); -}; - typedef AbstractRegSet RegSet; typedef AbstractRegSet FloatRegSet; typedef AbstractRegSet PRegSet; -template -class RegSetIterator { - AbstractRegSet _regs; - -public: - RegSetIterator(AbstractRegSet x): _regs(x) {} - RegSetIterator(const RegSetIterator& mit) : _regs(mit._regs) {} - - RegSetIterator& operator++() { - RegImpl r = _regs.first(); - if (r->is_valid()) - _regs -= r; - return *this; - } - - bool operator==(const RegSetIterator& rhs) const { - return _regs.bits() == rhs._regs.bits(); - } - bool operator!=(const RegSetIterator& rhs) const { - return ! (rhs == *this); - } - - RegImpl operator*() { - return _regs.first(); - } -}; - -template -inline RegSetIterator AbstractRegSet::begin() { - return RegSetIterator(*this); -} - template <> inline Register AbstractRegSet::first() { uint32_t first = _bitset & -_bitset; diff --git a/src/hotspot/cpu/aarch64/register_definitions_aarch64.cpp b/src/hotspot/cpu/aarch64/register_definitions_aarch64.cpp deleted file mode 100644 index f48c70d09e6707bbd58aa75674cdf668c912ec68..0000000000000000000000000000000000000000 --- a/src/hotspot/cpu/aarch64/register_definitions_aarch64.cpp +++ /dev/null @@ -1,208 +0,0 @@ -/* - * Copyright (c) 2002, 2020, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2014, Red Hat Inc. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -#include "precompiled.hpp" -#include "asm/assembler.hpp" -#include "asm/macroAssembler.inline.hpp" -#include "asm/register.hpp" -#include "register_aarch64.hpp" -# include "interp_masm_aarch64.hpp" - -REGISTER_DEFINITION(Register, noreg); - -REGISTER_DEFINITION(Register, r0); -REGISTER_DEFINITION(Register, r1); -REGISTER_DEFINITION(Register, r2); -REGISTER_DEFINITION(Register, r3); -REGISTER_DEFINITION(Register, r4); -REGISTER_DEFINITION(Register, r5); -REGISTER_DEFINITION(Register, r6); -REGISTER_DEFINITION(Register, r7); -REGISTER_DEFINITION(Register, r8); -REGISTER_DEFINITION(Register, r9); -REGISTER_DEFINITION(Register, r10); -REGISTER_DEFINITION(Register, r11); -REGISTER_DEFINITION(Register, r12); -REGISTER_DEFINITION(Register, r13); -REGISTER_DEFINITION(Register, r14); -REGISTER_DEFINITION(Register, r15); -REGISTER_DEFINITION(Register, r16); -REGISTER_DEFINITION(Register, r17); -REGISTER_DEFINITION(Register, r18_tls); // see comment in register_aarch64.hpp -REGISTER_DEFINITION(Register, r19); -REGISTER_DEFINITION(Register, r20); -REGISTER_DEFINITION(Register, r21); -REGISTER_DEFINITION(Register, r22); -REGISTER_DEFINITION(Register, r23); -REGISTER_DEFINITION(Register, r24); -REGISTER_DEFINITION(Register, r25); -REGISTER_DEFINITION(Register, r26); -REGISTER_DEFINITION(Register, r27); -REGISTER_DEFINITION(Register, r28); -REGISTER_DEFINITION(Register, r29); -REGISTER_DEFINITION(Register, r30); -REGISTER_DEFINITION(Register, sp); - -REGISTER_DEFINITION(FloatRegister, fnoreg); - -REGISTER_DEFINITION(FloatRegister, v0); -REGISTER_DEFINITION(FloatRegister, v1); -REGISTER_DEFINITION(FloatRegister, v2); -REGISTER_DEFINITION(FloatRegister, v3); -REGISTER_DEFINITION(FloatRegister, v4); -REGISTER_DEFINITION(FloatRegister, v5); -REGISTER_DEFINITION(FloatRegister, v6); -REGISTER_DEFINITION(FloatRegister, v7); -REGISTER_DEFINITION(FloatRegister, v8); -REGISTER_DEFINITION(FloatRegister, v9); -REGISTER_DEFINITION(FloatRegister, v10); -REGISTER_DEFINITION(FloatRegister, v11); -REGISTER_DEFINITION(FloatRegister, v12); -REGISTER_DEFINITION(FloatRegister, v13); -REGISTER_DEFINITION(FloatRegister, v14); -REGISTER_DEFINITION(FloatRegister, v15); -REGISTER_DEFINITION(FloatRegister, v16); -REGISTER_DEFINITION(FloatRegister, v17); -REGISTER_DEFINITION(FloatRegister, v18); -REGISTER_DEFINITION(FloatRegister, v19); -REGISTER_DEFINITION(FloatRegister, v20); -REGISTER_DEFINITION(FloatRegister, v21); -REGISTER_DEFINITION(FloatRegister, v22); -REGISTER_DEFINITION(FloatRegister, v23); -REGISTER_DEFINITION(FloatRegister, v24); -REGISTER_DEFINITION(FloatRegister, v25); -REGISTER_DEFINITION(FloatRegister, v26); -REGISTER_DEFINITION(FloatRegister, v27); -REGISTER_DEFINITION(FloatRegister, v28); -REGISTER_DEFINITION(FloatRegister, v29); -REGISTER_DEFINITION(FloatRegister, v30); -REGISTER_DEFINITION(FloatRegister, v31); - -REGISTER_DEFINITION(Register, zr); - -REGISTER_DEFINITION(Register, c_rarg0); -REGISTER_DEFINITION(Register, c_rarg1); -REGISTER_DEFINITION(Register, c_rarg2); -REGISTER_DEFINITION(Register, c_rarg3); -REGISTER_DEFINITION(Register, c_rarg4); -REGISTER_DEFINITION(Register, c_rarg5); -REGISTER_DEFINITION(Register, c_rarg6); -REGISTER_DEFINITION(Register, c_rarg7); - -REGISTER_DEFINITION(FloatRegister, c_farg0); -REGISTER_DEFINITION(FloatRegister, c_farg1); -REGISTER_DEFINITION(FloatRegister, c_farg2); -REGISTER_DEFINITION(FloatRegister, c_farg3); -REGISTER_DEFINITION(FloatRegister, c_farg4); -REGISTER_DEFINITION(FloatRegister, c_farg5); -REGISTER_DEFINITION(FloatRegister, c_farg6); -REGISTER_DEFINITION(FloatRegister, c_farg7); - -REGISTER_DEFINITION(Register, j_rarg0); -REGISTER_DEFINITION(Register, j_rarg1); -REGISTER_DEFINITION(Register, j_rarg2); -REGISTER_DEFINITION(Register, j_rarg3); -REGISTER_DEFINITION(Register, j_rarg4); -REGISTER_DEFINITION(Register, j_rarg5); -REGISTER_DEFINITION(Register, j_rarg6); -REGISTER_DEFINITION(Register, j_rarg7); - -REGISTER_DEFINITION(FloatRegister, j_farg0); -REGISTER_DEFINITION(FloatRegister, j_farg1); -REGISTER_DEFINITION(FloatRegister, j_farg2); -REGISTER_DEFINITION(FloatRegister, j_farg3); -REGISTER_DEFINITION(FloatRegister, j_farg4); -REGISTER_DEFINITION(FloatRegister, j_farg5); -REGISTER_DEFINITION(FloatRegister, j_farg6); -REGISTER_DEFINITION(FloatRegister, j_farg7); - -REGISTER_DEFINITION(Register, rscratch1); -REGISTER_DEFINITION(Register, rscratch2); -REGISTER_DEFINITION(Register, esp); -REGISTER_DEFINITION(Register, rdispatch); -REGISTER_DEFINITION(Register, rcpool); -REGISTER_DEFINITION(Register, rmonitors); -REGISTER_DEFINITION(Register, rlocals); -REGISTER_DEFINITION(Register, rmethod); -REGISTER_DEFINITION(Register, rbcp); - -REGISTER_DEFINITION(Register, lr); -REGISTER_DEFINITION(Register, rfp); -REGISTER_DEFINITION(Register, rthread); -REGISTER_DEFINITION(Register, rheapbase); - -REGISTER_DEFINITION(Register, r31_sp); - -REGISTER_DEFINITION(FloatRegister, z0); -REGISTER_DEFINITION(FloatRegister, z1); -REGISTER_DEFINITION(FloatRegister, z2); -REGISTER_DEFINITION(FloatRegister, z3); -REGISTER_DEFINITION(FloatRegister, z4); -REGISTER_DEFINITION(FloatRegister, z5); -REGISTER_DEFINITION(FloatRegister, z6); -REGISTER_DEFINITION(FloatRegister, z7); -REGISTER_DEFINITION(FloatRegister, z8); -REGISTER_DEFINITION(FloatRegister, z9); -REGISTER_DEFINITION(FloatRegister, z10); -REGISTER_DEFINITION(FloatRegister, z11); -REGISTER_DEFINITION(FloatRegister, z12); -REGISTER_DEFINITION(FloatRegister, z13); -REGISTER_DEFINITION(FloatRegister, z14); -REGISTER_DEFINITION(FloatRegister, z15); -REGISTER_DEFINITION(FloatRegister, z16); -REGISTER_DEFINITION(FloatRegister, z17); -REGISTER_DEFINITION(FloatRegister, z18); -REGISTER_DEFINITION(FloatRegister, z19); -REGISTER_DEFINITION(FloatRegister, z20); -REGISTER_DEFINITION(FloatRegister, z21); -REGISTER_DEFINITION(FloatRegister, z22); -REGISTER_DEFINITION(FloatRegister, z23); -REGISTER_DEFINITION(FloatRegister, z24); -REGISTER_DEFINITION(FloatRegister, z25); -REGISTER_DEFINITION(FloatRegister, z26); -REGISTER_DEFINITION(FloatRegister, z27); -REGISTER_DEFINITION(FloatRegister, z28); -REGISTER_DEFINITION(FloatRegister, z29); -REGISTER_DEFINITION(FloatRegister, z30); -REGISTER_DEFINITION(FloatRegister, z31); - -REGISTER_DEFINITION(PRegister, p0); -REGISTER_DEFINITION(PRegister, p1); -REGISTER_DEFINITION(PRegister, p2); -REGISTER_DEFINITION(PRegister, p3); -REGISTER_DEFINITION(PRegister, p4); -REGISTER_DEFINITION(PRegister, p5); -REGISTER_DEFINITION(PRegister, p6); -REGISTER_DEFINITION(PRegister, p7); -REGISTER_DEFINITION(PRegister, p8); -REGISTER_DEFINITION(PRegister, p9); -REGISTER_DEFINITION(PRegister, p10); -REGISTER_DEFINITION(PRegister, p11); -REGISTER_DEFINITION(PRegister, p12); -REGISTER_DEFINITION(PRegister, p13); -REGISTER_DEFINITION(PRegister, p14); -REGISTER_DEFINITION(PRegister, p15); - -REGISTER_DEFINITION(PRegister, ptrue); diff --git a/src/hotspot/cpu/aarch64/sharedRuntime_aarch64.cpp b/src/hotspot/cpu/aarch64/sharedRuntime_aarch64.cpp index 08cc2b20a61e2ad6d33f09446d29942057009db9..18c6d227823075bcf802fde79cec599eb387c952 100644 --- a/src/hotspot/cpu/aarch64/sharedRuntime_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/sharedRuntime_aarch64.cpp @@ -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. * 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. @@ -410,6 +410,7 @@ static void patch_callers_callsite(MacroAssembler *masm) { __ mov(c_rarg0, rmethod); __ mov(c_rarg1, lr); + __ authenticate_return_address(c_rarg1, rscratch1); __ lea(rscratch1, RuntimeAddress(CAST_FROM_FN_PTR(address, SharedRuntime::fixup_callers_callsite))); __ blr(rscratch1); @@ -2178,8 +2179,8 @@ void SharedRuntime::generate_deopt_blob() { // load throwing pc from JavaThread and patch it as the return address // of the current frame. Then clear the field in JavaThread - __ ldr(r3, Address(rthread, JavaThread::exception_pc_offset())); + __ protect_return_address(r3, rscratch1); __ str(r3, Address(rfp, wordSize)); __ str(zr, Address(rthread, JavaThread::exception_pc_offset())); @@ -2287,6 +2288,7 @@ void SharedRuntime::generate_deopt_blob() { __ sub(r2, r2, 2 * wordSize); __ add(sp, sp, r2); __ ldp(rfp, lr, __ post(sp, 2 * wordSize)); + __ authenticate_return_address(); // LR should now be the return address to the caller (3) #ifdef ASSERT @@ -2428,6 +2430,7 @@ void SharedRuntime::generate_uncommon_trap_blob() { // Push self-frame. We get here with a return address in LR // and sp should be 16 byte aligned // push rfp and retaddr by hand + __ protect_return_address(); __ stp(rfp, lr, Address(__ pre(sp, -2 * wordSize))); // we don't expect an arg reg save area #ifndef PRODUCT @@ -2502,6 +2505,7 @@ void SharedRuntime::generate_uncommon_trap_blob() { __ sub(r2, r2, 2 * wordSize); __ add(sp, sp, r2); __ ldp(rfp, lr, __ post(sp, 2 * wordSize)); + __ authenticate_return_address(); // LR should now be the return address to the caller (3) frame #ifdef ASSERT @@ -2624,6 +2628,11 @@ SafepointBlob* SharedRuntime::generate_handler_blob(address call_ptr, int poll_t bool cause_return = (poll_type == POLL_AT_RETURN); RegisterSaver reg_save(poll_type == POLL_AT_VECTOR_LOOP /* save_vectors */); + // When the signal occured, the LR was either signed and stored on the stack (in which + // case it will be restored from the stack before being used) or unsigned and not stored + // on the stack. Stipping ensures we get the right value. + __ strip_return_address(); + // Save Integer and Float registers. map = reg_save.save_live_registers(masm, 0, &frame_size_in_words); @@ -2643,6 +2652,7 @@ SafepointBlob* SharedRuntime::generate_handler_blob(address call_ptr, int poll_t // it later to determine if someone changed the return address for // us! __ ldr(r20, Address(rthread, JavaThread::saved_exception_pc_offset())); + __ protect_return_address(r20, rscratch1); __ str(r20, Address(rfp, wordSize)); } @@ -2683,6 +2693,7 @@ SafepointBlob* SharedRuntime::generate_handler_blob(address call_ptr, int poll_t __ ldr(rscratch1, Address(rfp, wordSize)); __ cmp(r20, rscratch1); __ br(Assembler::NE, no_adjust); + __ authenticate_return_address(r20, rscratch1); #ifdef ASSERT // Verify the correct encoding of the poll we're about to skip. @@ -2697,6 +2708,7 @@ SafepointBlob* SharedRuntime::generate_handler_blob(address call_ptr, int poll_t #endif // Adjust return pc forward to step over the safepoint poll instruction __ add(r20, r20, NativeInstruction::instruction_size); + __ protect_return_address(r20, rscratch1); __ str(r20, Address(rfp, wordSize)); } @@ -2857,6 +2869,7 @@ void OptoRuntime::generate_exception_blob() { // push rfp and retaddr by hand // Exception pc is 'return address' for stack walker + __ protect_return_address(); __ stp(rfp, lr, Address(__ pre(sp, -2 * wordSize))); // there are no callee save registers and we don't expect an // arg reg save area @@ -2910,6 +2923,7 @@ void OptoRuntime::generate_exception_blob() { // there are no callee save registers now that adapter frames are gone. // and we dont' expect an arg reg save area __ ldp(rfp, r3, Address(__ post(sp, 2 * wordSize))); + __ authenticate_return_address(r3); // r0: exception handler diff --git a/src/hotspot/cpu/aarch64/stubGenerator_aarch64.cpp b/src/hotspot/cpu/aarch64/stubGenerator_aarch64.cpp index a26c4a1597625ec1ceafbdcf12384def1b38cf22..1b41f09d97221799ac92ee3e430b10298193c663 100644 --- a/src/hotspot/cpu/aarch64/stubGenerator_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/stubGenerator_aarch64.cpp @@ -26,6 +26,7 @@ #include "precompiled.hpp" #include "asm/macroAssembler.hpp" #include "asm/macroAssembler.inline.hpp" +#include "asm/register.hpp" #include "atomic_aarch64.hpp" #include "compiler/oopMap.hpp" #include "gc/shared/barrierSet.hpp" @@ -1320,10 +1321,10 @@ class StubGenerator: public StubCodeGenerator { void clobber_registers() { #ifdef ASSERT RegSet clobbered - = MacroAssembler::call_clobbered_registers() - rscratch1; + = MacroAssembler::call_clobbered_gp_registers() - rscratch1; __ mov(rscratch1, (uint64_t)0xdeadbeef); __ orr(rscratch1, rscratch1, rscratch1, Assembler::LSL, 32); - for (RegSetIterator<> it = clobbered.begin(); *it != noreg; ++it) { + for (RegSetIterator it = clobbered.begin(); *it != noreg; ++it) { __ mov(*it, rscratch1); } #endif @@ -4657,7 +4658,7 @@ class StubGenerator: public StubCodeGenerator { return start; } - address generate_has_negatives(address &has_negatives_long) { + address generate_count_positives(address &count_positives_long) { const u1 large_loop_size = 64; const uint64_t UPPER_BIT_MASK=0x8080808080808080; int dcache_line = VM_Version::dcache_line_size(); @@ -4666,13 +4667,15 @@ class StubGenerator: public StubCodeGenerator { __ align(CodeEntryAlignment); - StubCodeMark mark(this, "StubRoutines", "has_negatives"); + StubCodeMark mark(this, "StubRoutines", "count_positives"); address entry = __ pc(); __ enter(); + // precondition: a copy of len is already in result + // __ mov(result, len); - Label RET_TRUE, RET_TRUE_NO_POP, RET_FALSE, ALIGNED, LOOP16, CHECK_16, DONE, + Label RET_ADJUST, RET_ADJUST_16, RET_ADJUST_LONG, RET_NO_POP, RET_LEN, ALIGNED, LOOP16, CHECK_16, LARGE_LOOP, POST_LOOP16, LEN_OVER_15, LEN_OVER_8, POST_LOOP16_LOAD_TAIL; __ cmp(len, (u1)15); @@ -4686,25 +4689,26 @@ class StubGenerator: public StubCodeGenerator { __ sub(rscratch1, zr, len, __ LSL, 3); // LSL 3 is to get bits from bytes. __ lsrv(rscratch2, rscratch2, rscratch1); __ tst(rscratch2, UPPER_BIT_MASK); - __ cset(result, Assembler::NE); + __ csel(result, zr, result, Assembler::NE); __ leave(); __ ret(lr); __ bind(LEN_OVER_8); __ ldp(rscratch1, rscratch2, Address(ary1, -16)); __ sub(len, len, 8); // no data dep., then sub can be executed while loading __ tst(rscratch2, UPPER_BIT_MASK); - __ br(Assembler::NE, RET_TRUE_NO_POP); + __ br(Assembler::NE, RET_NO_POP); __ sub(rscratch2, zr, len, __ LSL, 3); // LSL 3 is to get bits from bytes __ lsrv(rscratch1, rscratch1, rscratch2); __ tst(rscratch1, UPPER_BIT_MASK); - __ cset(result, Assembler::NE); + __ bind(RET_NO_POP); + __ csel(result, zr, result, Assembler::NE); __ leave(); __ ret(lr); Register tmp1 = r3, tmp2 = r4, tmp3 = r5, tmp4 = r6, tmp5 = r7, tmp6 = r10; const RegSet spilled_regs = RegSet::range(tmp1, tmp5) + tmp6; - has_negatives_long = __ pc(); // 2nd entry point + count_positives_long = __ pc(); // 2nd entry point __ enter(); @@ -4716,10 +4720,10 @@ class StubGenerator: public StubCodeGenerator { __ mov(tmp5, 16); __ sub(rscratch1, tmp5, rscratch2); // amount of bytes until aligned address __ add(ary1, ary1, rscratch1); - __ sub(len, len, rscratch1); __ orr(tmp6, tmp6, tmp1); __ tst(tmp6, UPPER_BIT_MASK); - __ br(Assembler::NE, RET_TRUE); + __ br(Assembler::NE, RET_ADJUST); + __ sub(len, len, rscratch1); __ bind(ALIGNED); __ cmp(len, large_loop_size); @@ -4734,7 +4738,7 @@ class StubGenerator: public StubCodeGenerator { __ sub(len, len, 16); __ orr(tmp6, tmp6, tmp1); __ tst(tmp6, UPPER_BIT_MASK); - __ br(Assembler::NE, RET_TRUE); + __ br(Assembler::NE, RET_ADJUST_16); __ cmp(len, large_loop_size); __ br(Assembler::LT, CHECK_16); @@ -4766,7 +4770,7 @@ class StubGenerator: public StubCodeGenerator { __ orr(rscratch1, rscratch1, tmp6); __ orr(tmp2, tmp2, rscratch1); __ tst(tmp2, UPPER_BIT_MASK); - __ br(Assembler::NE, RET_TRUE); + __ br(Assembler::NE, RET_ADJUST_LONG); __ cmp(len, large_loop_size); __ br(Assembler::GE, LARGE_LOOP); @@ -4779,7 +4783,7 @@ class StubGenerator: public StubCodeGenerator { __ sub(len, len, 16); __ orr(tmp2, tmp2, tmp3); __ tst(tmp2, UPPER_BIT_MASK); - __ br(Assembler::NE, RET_TRUE); + __ br(Assembler::NE, RET_ADJUST_16); __ cmp(len, (u1)16); __ br(Assembler::GE, LOOP16); // 16-byte load loop end @@ -4787,37 +4791,38 @@ class StubGenerator: public StubCodeGenerator { __ cmp(len, (u1)8); __ br(Assembler::LE, POST_LOOP16_LOAD_TAIL); __ ldr(tmp3, Address(__ post(ary1, 8))); - __ sub(len, len, 8); __ tst(tmp3, UPPER_BIT_MASK); - __ br(Assembler::NE, RET_TRUE); + __ br(Assembler::NE, RET_ADJUST); + __ sub(len, len, 8); __ bind(POST_LOOP16_LOAD_TAIL); - __ cbz(len, RET_FALSE); // Can't shift left by 64 when len==0 + __ cbz(len, RET_LEN); // Can't shift left by 64 when len==0 __ ldr(tmp1, Address(ary1)); __ mov(tmp2, 64); __ sub(tmp4, tmp2, len, __ LSL, 3); __ lslv(tmp1, tmp1, tmp4); __ tst(tmp1, UPPER_BIT_MASK); - __ br(Assembler::NE, RET_TRUE); + __ br(Assembler::NE, RET_ADJUST); // Fallthrough - __ bind(RET_FALSE); + __ bind(RET_LEN); __ pop(spilled_regs, sp); __ leave(); - __ mov(result, zr); __ ret(lr); - __ bind(RET_TRUE); - __ pop(spilled_regs, sp); - __ bind(RET_TRUE_NO_POP); - __ leave(); - __ mov(result, 1); - __ ret(lr); + // difference result - len is the count of guaranteed to be + // positive bytes - __ bind(DONE); + __ bind(RET_ADJUST_LONG); + __ add(len, len, (u1)(large_loop_size - 16)); + __ bind(RET_ADJUST_16); + __ add(len, len, 16); + __ bind(RET_ADJUST); __ pop(spilled_regs, sp); __ leave(); + __ sub(result, result, len); __ ret(lr); + return entry; } @@ -6625,7 +6630,7 @@ class StubGenerator: public StubCodeGenerator { // Register allocation - RegSetIterator<> regs = (RegSet::range(r0, r26) - r18_tls).begin(); + RegSetIterator regs = (RegSet::range(r0, r26) - r18_tls).begin(); Pa_base = *regs; // Argument registers if (squaring) Pb_base = Pa_base; @@ -7519,8 +7524,8 @@ class StubGenerator: public StubCodeGenerator { // arraycopy stubs used by compilers generate_arraycopy_stubs(); - // has negatives stub for large arrays. - StubRoutines::aarch64::_has_negatives = generate_has_negatives(StubRoutines::aarch64::_has_negatives_long); + // countPositives stub for large arrays. + StubRoutines::aarch64::_count_positives = generate_count_positives(StubRoutines::aarch64::_count_positives_long); // array equals stub for large arrays. if (!UseSimpleArrayEquals) { diff --git a/src/hotspot/cpu/aarch64/stubRoutines_aarch64.cpp b/src/hotspot/cpu/aarch64/stubRoutines_aarch64.cpp index 9e16a1f9f8812268779be2caad8e459c123816ae..2e1c4b695425274c4f41223cf36e1ded7507dfa2 100644 --- a/src/hotspot/cpu/aarch64/stubRoutines_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/stubRoutines_aarch64.cpp @@ -45,8 +45,8 @@ address StubRoutines::aarch64::_float_sign_flip = NULL; address StubRoutines::aarch64::_double_sign_mask = NULL; address StubRoutines::aarch64::_double_sign_flip = NULL; address StubRoutines::aarch64::_zero_blocks = NULL; -address StubRoutines::aarch64::_has_negatives = NULL; -address StubRoutines::aarch64::_has_negatives_long = NULL; +address StubRoutines::aarch64::_count_positives = NULL; +address StubRoutines::aarch64::_count_positives_long = NULL; address StubRoutines::aarch64::_large_array_equals = NULL; address StubRoutines::aarch64::_compare_long_string_LL = NULL; address StubRoutines::aarch64::_compare_long_string_UU = NULL; diff --git a/src/hotspot/cpu/aarch64/stubRoutines_aarch64.hpp b/src/hotspot/cpu/aarch64/stubRoutines_aarch64.hpp index 295264b7aaf22067503fcbc7fb3db2cab7222870..a17e7540e42d24eac8f2db642c7d1f0c407b75ba 100644 --- a/src/hotspot/cpu/aarch64/stubRoutines_aarch64.hpp +++ b/src/hotspot/cpu/aarch64/stubRoutines_aarch64.hpp @@ -58,8 +58,6 @@ class aarch64 { static address _zero_blocks; - static address _has_negatives; - static address _has_negatives_long; static address _large_array_equals; static address _compare_long_string_LL; static address _compare_long_string_LU; @@ -78,6 +76,9 @@ class aarch64 { public: + static address _count_positives; + static address _count_positives_long; + static address get_previous_sp_entry() { return _get_previous_sp_entry; @@ -131,12 +132,12 @@ class aarch64 { return _zero_blocks; } - static address has_negatives() { - return _has_negatives; + static address count_positives() { + return _count_positives; } - static address has_negatives_long() { - return _has_negatives_long; + static address count_positives_long() { + return _count_positives_long; } static address large_array_equals() { diff --git a/src/hotspot/cpu/aarch64/templateInterpreterGenerator_aarch64.cpp b/src/hotspot/cpu/aarch64/templateInterpreterGenerator_aarch64.cpp index e20cffd57670b49e7ee7372a5432f1a0c1249e2b..bf0a4e4472927e33b12b18c2ea8a310b665c3758 100644 --- a/src/hotspot/cpu/aarch64/templateInterpreterGenerator_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/templateInterpreterGenerator_aarch64.cpp @@ -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. * Copyright (c) 2014, 2020, Red Hat Inc. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -832,6 +832,7 @@ void TemplateInterpreterGenerator::generate_fixed_frame(bool native_call) { __ ldr(rcpool, Address(rcpool, ConstantPool::cache_offset_in_bytes())); __ stp(rlocals, rcpool, Address(sp, 2 * wordSize)); + __ protect_return_address(); __ stp(rfp, lr, Address(sp, 10 * wordSize)); __ lea(rfp, Address(sp, 10 * wordSize)); @@ -1748,6 +1749,8 @@ void TemplateInterpreterGenerator::generate_throw_exception() { // adapter frames in C2. Label caller_not_deoptimized; __ ldr(c_rarg1, Address(rfp, frame::return_addr_offset * wordSize)); + // This is a return address, so requires authenticating for PAC. + __ authenticate_return_address(c_rarg1, rscratch1); __ super_call_VM_leaf(CAST_FROM_FN_PTR(address, InterpreterRuntime::interpreter_contains), c_rarg1); __ cbnz(r0, caller_not_deoptimized); @@ -1937,6 +1940,7 @@ void TemplateInterpreterGenerator::set_vtos_entry_points(Template* t, address TemplateInterpreterGenerator::generate_trace_code(TosState state) { address entry = __ pc(); + __ protect_return_address(); __ push(lr); __ push(state); __ push(RegSet::range(r0, r15), sp); @@ -1947,6 +1951,7 @@ address TemplateInterpreterGenerator::generate_trace_code(TosState state) { __ pop(RegSet::range(r0, r15), sp); __ pop(state); __ pop(lr); + __ authenticate_return_address(); __ ret(lr); // return from result handler return entry; diff --git a/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp b/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp index b0c0c64f6d93b52b08384a1e01c0845c6861f71c..d2a573ac63bd6880060d33f45cd095e084061b4b 100644 --- a/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp @@ -45,6 +45,7 @@ int VM_Version::_zva_length; int VM_Version::_dcache_line_size; int VM_Version::_icache_line_size; int VM_Version::_initial_sve_vector_length; +bool VM_Version::_rop_protection; SpinWait VM_Version::_spin_wait; @@ -409,6 +410,39 @@ void VM_Version::initialize() { UsePopCountInstruction = true; } + if (UseBranchProtection == nullptr || strcmp(UseBranchProtection, "none") == 0) { + _rop_protection = false; + } else if (strcmp(UseBranchProtection, "standard") == 0) { + _rop_protection = false; + // Enable PAC if this code has been built with branch-protection and the CPU/OS supports it. +#ifdef __ARM_FEATURE_PAC_DEFAULT + if ((_features & CPU_PACA) != 0) { + _rop_protection = true; + } +#endif + } else if (strcmp(UseBranchProtection, "pac-ret") == 0) { + _rop_protection = true; +#ifdef __ARM_FEATURE_PAC_DEFAULT + if ((_features & CPU_PACA) == 0) { + warning("ROP-protection specified, but not supported on this CPU."); + // Disable PAC to prevent illegal instruction crashes. + _rop_protection = false; + } +#else + warning("ROP-protection specified, but this VM was built without ROP-protection support."); +#endif + } else { + vm_exit_during_initialization(err_msg("Unsupported UseBranchProtection: %s", UseBranchProtection)); + } + + // The frame pointer must be preserved for ROP protection. + if (_rop_protection == true) { + if (FLAG_IS_DEFAULT(PreserveFramePointer) == false && PreserveFramePointer == false ) { + vm_exit_during_initialization(err_msg("PreserveFramePointer cannot be disabled for ROP-protection")); + } + PreserveFramePointer = true; + } + #ifdef COMPILER2 if (FLAG_IS_DEFAULT(UseMultiplyToLenIntrinsic)) { UseMultiplyToLenIntrinsic = true; diff --git a/src/hotspot/cpu/aarch64/vm_version_aarch64.hpp b/src/hotspot/cpu/aarch64/vm_version_aarch64.hpp index b6aec7ed01f985c97b009fb2dde99b73df3b7af8..e979f62b926c78c927f59b716c4d8fcff1f380a1 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, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2022, 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. * @@ -45,6 +45,7 @@ protected: static int _dcache_line_size; static int _icache_line_size; static int _initial_sve_vector_length; + static bool _rop_protection; static SpinWait _spin_wait; @@ -114,10 +115,11 @@ public: decl(SHA3, "sha3", 17) \ decl(SHA512, "sha512", 21) \ decl(SVE, "sve", 22) \ + decl(PACA, "paca", 30) \ /* flags above must follow Linux HWCAP */ \ decl(SVE2, "sve2", 28) \ decl(STXR_PREFETCH, "stxr_prefetch", 29) \ - decl(A53MAC, "a53mac", 30) + decl(A53MAC, "a53mac", 31) #define DECLARE_CPU_FEATURE_FLAG(id, name, bit) CPU_##id = (1 << bit), CPU_FEATURE_FLAGS(DECLARE_CPU_FEATURE_FLAG) @@ -156,6 +158,7 @@ public: static void initialize_cpu_information(void); + static bool use_rop_protection() { return _rop_protection; } }; #endif // CPU_AARCH64_VM_VERSION_AARCH64_HPP diff --git a/src/hotspot/cpu/arm/frame_arm.inline.hpp b/src/hotspot/cpu/arm/frame_arm.inline.hpp index 835edd68493e66e82345eb848d304c0202e27b79..773b6d06f7b4c426052eb7b2d357730c78bc3f20 100644 --- a/src/hotspot/cpu/arm/frame_arm.inline.hpp +++ b/src/hotspot/cpu/arm/frame_arm.inline.hpp @@ -124,9 +124,13 @@ inline intptr_t* frame::id(void) const { return unextended_sp(); } inline bool frame::is_older(intptr_t* id) const { assert(this->id() != NULL && id != NULL, "NULL frame id"); return this->id() > id ; } - inline intptr_t* frame::link() const { return (intptr_t*) *(intptr_t **)addr_at(link_offset); } +inline intptr_t* frame::link_or_null() const { + intptr_t** ptr = (intptr_t **)addr_at(link_offset); + return os::is_readable_pointer(ptr) ? *ptr : NULL; +} + inline intptr_t* frame::unextended_sp() const { return _unextended_sp; } // Return address: diff --git a/src/hotspot/cpu/arm/matcher_arm.hpp b/src/hotspot/cpu/arm/matcher_arm.hpp index 7552b014c061eaba521fc77f472cbf3fe76a8722..496ea27c0861b0d1a8ae1ca2dbc712bc40e48467 100644 --- a/src/hotspot/cpu/arm/matcher_arm.hpp +++ b/src/hotspot/cpu/arm/matcher_arm.hpp @@ -155,4 +155,9 @@ // Implements a variant of EncodeISOArrayNode that encode ASCII only static const bool supports_encode_ascii_array = false; + // Returns pre-selection estimated cost of a vector operation. + static int vector_op_pre_select_sz_estimate(int vopc, BasicType ety, int vlen) { + return 0; + } + #endif // CPU_ARM_MATCHER_ARM_HPP diff --git a/src/hotspot/cpu/arm/register_definitions_arm.cpp b/src/hotspot/cpu/arm/register_definitions_arm.cpp deleted file mode 100644 index 4aa7714970cbb1e0ebe4ed38983c56cf4a7bff72..0000000000000000000000000000000000000000 --- a/src/hotspot/cpu/arm/register_definitions_arm.cpp +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Copyright (c) 2008, 2016, Oracle and/or its affiliates. All rights reserved. - * 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 "precompiled.hpp" -#include "asm/assembler.hpp" -#include "asm/register.hpp" -#include "interp_masm_arm.hpp" -#include "register_arm.hpp" - -REGISTER_DEFINITION(Register, noreg); -REGISTER_DEFINITION(FloatRegister, fnoreg); - - -REGISTER_DEFINITION(FloatRegister, S0); -REGISTER_DEFINITION(FloatRegister, S1_reg); -REGISTER_DEFINITION(FloatRegister, S2_reg); -REGISTER_DEFINITION(FloatRegister, S3_reg); -REGISTER_DEFINITION(FloatRegister, S4_reg); -REGISTER_DEFINITION(FloatRegister, S5_reg); -REGISTER_DEFINITION(FloatRegister, S6_reg); -REGISTER_DEFINITION(FloatRegister, S7); -REGISTER_DEFINITION(FloatRegister, S8); -REGISTER_DEFINITION(FloatRegister, S9); -REGISTER_DEFINITION(FloatRegister, S10); -REGISTER_DEFINITION(FloatRegister, S11); -REGISTER_DEFINITION(FloatRegister, S12); -REGISTER_DEFINITION(FloatRegister, S13); -REGISTER_DEFINITION(FloatRegister, S14); -REGISTER_DEFINITION(FloatRegister, S15); -REGISTER_DEFINITION(FloatRegister, S16); -REGISTER_DEFINITION(FloatRegister, S17); -REGISTER_DEFINITION(FloatRegister, S18); -REGISTER_DEFINITION(FloatRegister, S19); -REGISTER_DEFINITION(FloatRegister, S20); -REGISTER_DEFINITION(FloatRegister, S21); -REGISTER_DEFINITION(FloatRegister, S22); -REGISTER_DEFINITION(FloatRegister, S23); -REGISTER_DEFINITION(FloatRegister, S24); -REGISTER_DEFINITION(FloatRegister, S25); -REGISTER_DEFINITION(FloatRegister, S26); -REGISTER_DEFINITION(FloatRegister, S27); -REGISTER_DEFINITION(FloatRegister, S28); -REGISTER_DEFINITION(FloatRegister, S29); -REGISTER_DEFINITION(FloatRegister, S30); -REGISTER_DEFINITION(FloatRegister, S31); -REGISTER_DEFINITION(FloatRegister, Stemp); -REGISTER_DEFINITION(FloatRegister, D0); -REGISTER_DEFINITION(FloatRegister, D1); -REGISTER_DEFINITION(FloatRegister, D2); -REGISTER_DEFINITION(FloatRegister, D3); -REGISTER_DEFINITION(FloatRegister, D4); -REGISTER_DEFINITION(FloatRegister, D5); -REGISTER_DEFINITION(FloatRegister, D6); -REGISTER_DEFINITION(FloatRegister, D7); -REGISTER_DEFINITION(FloatRegister, D8); -REGISTER_DEFINITION(FloatRegister, D9); -REGISTER_DEFINITION(FloatRegister, D10); -REGISTER_DEFINITION(FloatRegister, D11); -REGISTER_DEFINITION(FloatRegister, D12); -REGISTER_DEFINITION(FloatRegister, D13); -REGISTER_DEFINITION(FloatRegister, D14); -REGISTER_DEFINITION(FloatRegister, D15); -REGISTER_DEFINITION(FloatRegister, D16); -REGISTER_DEFINITION(FloatRegister, D17); -REGISTER_DEFINITION(FloatRegister, D18); -REGISTER_DEFINITION(FloatRegister, D19); -REGISTER_DEFINITION(FloatRegister, D20); -REGISTER_DEFINITION(FloatRegister, D21); -REGISTER_DEFINITION(FloatRegister, D22); -REGISTER_DEFINITION(FloatRegister, D23); -REGISTER_DEFINITION(FloatRegister, D24); -REGISTER_DEFINITION(FloatRegister, D25); -REGISTER_DEFINITION(FloatRegister, D26); -REGISTER_DEFINITION(FloatRegister, D27); -REGISTER_DEFINITION(FloatRegister, D28); -REGISTER_DEFINITION(FloatRegister, D29); -REGISTER_DEFINITION(FloatRegister, D30); -REGISTER_DEFINITION(FloatRegister, D31); - diff --git a/src/hotspot/cpu/ppc/c2_MacroAssembler_ppc.cpp b/src/hotspot/cpu/ppc/c2_MacroAssembler_ppc.cpp index 1ae5c13e62e97e0157ba8367b69369b7d3991ee0..30104094983b579eb68c5a959958fdd9ae0af5ba 100644 --- a/src/hotspot/cpu/ppc/c2_MacroAssembler_ppc.cpp +++ b/src/hotspot/cpu/ppc/c2_MacroAssembler_ppc.cpp @@ -565,16 +565,16 @@ void C2_MacroAssembler::string_indexof_char(Register result, Register haystack, } // string_indexof_char -void C2_MacroAssembler::has_negatives(Register src, Register cnt, Register result, - Register tmp1, Register tmp2) { +void C2_MacroAssembler::count_positives(Register src, Register cnt, Register result, + Register tmp1, Register tmp2) { const Register tmp0 = R0; assert_different_registers(src, result, cnt, tmp0, tmp1, tmp2); - Label Lfastloop, Lslow, Lloop, Lnoneg, Ldone; + Label Lfastloop, Lslow, Lloop, Ldone; // Check if cnt >= 8 (= 16 bytes) lis(tmp1, (int)(short)0x8080); // tmp1 = 0x8080808080808080 srwi_(tmp2, cnt, 4); - li(result, 1); // Assume there's a negative byte. + mr(result, src); // Use result reg to point to the current position. beq(CCR0, Lslow); ori(tmp1, tmp1, 0x8080); rldimi(tmp1, tmp1, 32, 0); @@ -582,30 +582,28 @@ void C2_MacroAssembler::has_negatives(Register src, Register cnt, Register resul // 2x unrolled loop bind(Lfastloop); - ld(tmp2, 0, src); - ld(tmp0, 8, src); + ld(tmp2, 0, result); + ld(tmp0, 8, result); orr(tmp0, tmp2, tmp0); and_(tmp0, tmp0, tmp1); - bne(CCR0, Ldone); // Found negative byte. - addi(src, src, 16); - + bne(CCR0, Lslow); // Found negative byte. + addi(result, result, 16); bdnz(Lfastloop); - bind(Lslow); // Fallback to slow version - rldicl_(tmp0, cnt, 0, 64-4); - beq(CCR0, Lnoneg); + bind(Lslow); // Fallback to slow version. + subf(tmp0, src, result); // Bytes known positive. + subf_(tmp0, tmp0, cnt); // Remaining Bytes. + beq(CCR0, Ldone); mtctr(tmp0); bind(Lloop); - lbz(tmp0, 0, src); - addi(src, src, 1); + lbz(tmp0, 0, result); andi_(tmp0, tmp0, 0x80); bne(CCR0, Ldone); // Found negative byte. + addi(result, result, 1); bdnz(Lloop); - bind(Lnoneg); - li(result, 0); bind(Ldone); + subf(result, src, result); // Result is offset from src. } - diff --git a/src/hotspot/cpu/ppc/c2_MacroAssembler_ppc.hpp b/src/hotspot/cpu/ppc/c2_MacroAssembler_ppc.hpp index 9c4576f2eaf043f0be28ef27f56c348cae1d5de7..ef4840b08a256c61d1add926f43eb255c9551e8c 100644 --- a/src/hotspot/cpu/ppc/c2_MacroAssembler_ppc.hpp +++ b/src/hotspot/cpu/ppc/c2_MacroAssembler_ppc.hpp @@ -63,6 +63,6 @@ void string_indexof_char(Register result, Register haystack, Register haycnt, Register needle, jchar needleChar, Register tmp1, Register tmp2, bool is_byte); - void has_negatives(Register src, Register cnt, Register result, Register tmp1, Register tmp2); + void count_positives(Register src, Register cnt, Register result, Register tmp1, Register tmp2); #endif // CPU_PPC_C2_MACROASSEMBLER_PPC_HPP diff --git a/src/hotspot/cpu/ppc/copy_ppc.hpp b/src/hotspot/cpu/ppc/copy_ppc.hpp index 06eae3c3f098054ecfae68a12ef6b1944aa21f13..0ae84b4e5959553042defa0ab7e203703831752d 100644 --- a/src/hotspot/cpu/ppc/copy_ppc.hpp +++ b/src/hotspot/cpu/ppc/copy_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, 2013 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -53,21 +53,7 @@ static void pd_disjoint_words(const HeapWord* from, HeapWord* to, size_t count) } static void pd_disjoint_words_atomic(const HeapWord* from, HeapWord* to, size_t count) { - switch (count) { - case 8: to[7] = from[7]; - case 7: to[6] = from[6]; - case 6: to[5] = from[5]; - case 5: to[4] = from[4]; - case 4: to[3] = from[3]; - case 3: to[2] = from[2]; - case 2: to[1] = from[1]; - case 1: to[0] = from[0]; - case 0: break; - default: while (count-- > 0) { - *to++ = *from++; - } - break; - } + shared_disjoint_words_atomic(from, to, count); } static void pd_aligned_conjoint_words(const HeapWord* from, HeapWord* to, size_t count) { diff --git a/src/hotspot/cpu/ppc/frame_ppc.inline.hpp b/src/hotspot/cpu/ppc/frame_ppc.inline.hpp index 705b4abefdbd77ead3ef07ee0aca064df1d8aeaa..239db8224c0c38f811ca717d08e09316b0c7fce3 100644 --- a/src/hotspot/cpu/ppc/frame_ppc.inline.hpp +++ b/src/hotspot/cpu/ppc/frame_ppc.inline.hpp @@ -117,6 +117,10 @@ inline intptr_t* frame::link() const { return (intptr_t*)callers_abi()->callers_sp; } +inline intptr_t* frame::link_or_null() const { + return link(); +} + inline intptr_t* frame::real_fp() const { return fp(); } diff --git a/src/hotspot/cpu/ppc/matcher_ppc.hpp b/src/hotspot/cpu/ppc/matcher_ppc.hpp index df2074dee24001b286dc90d0f27392cb7ec2d9f5..069c40485fea5adbc64851b83a62dd2a9cca1b50 100644 --- a/src/hotspot/cpu/ppc/matcher_ppc.hpp +++ b/src/hotspot/cpu/ppc/matcher_ppc.hpp @@ -164,4 +164,10 @@ // Implements a variant of EncodeISOArrayNode that encode ASCII only static const bool supports_encode_ascii_array = true; + // Returns pre-selection estimated cost of a vector operation. + static int vector_op_pre_select_sz_estimate(int vopc, BasicType ety, int vlen) { + return 0; + } + + #endif // CPU_PPC_MATCHER_PPC_HPP diff --git a/src/hotspot/cpu/ppc/ppc.ad b/src/hotspot/cpu/ppc/ppc.ad index 832982deb4552f1477017ba7ab174dacd72c1e47..b41c72ab449589687e5e1aed564ab56685f5aef4 100644 --- a/src/hotspot/cpu/ppc/ppc.ad +++ b/src/hotspot/cpu/ppc/ppc.ad @@ -12779,16 +12779,16 @@ instruct string_inflate(Universe dummy, rarg1RegP src, rarg2RegP dst, iRegIsrc l %} // StringCoding.java intrinsics -instruct has_negatives(rarg1RegP ary1, iRegIsrc len, iRegIdst result, iRegLdst tmp1, iRegLdst tmp2, - regCTR ctr, flagsRegCR0 cr0) +instruct count_positives(iRegPsrc ary1, iRegIsrc len, iRegIdst result, iRegLdst tmp1, iRegLdst tmp2, + regCTR ctr, flagsRegCR0 cr0) %{ - match(Set result (HasNegatives ary1 len)); - effect(TEMP_DEF result, USE_KILL ary1, TEMP tmp1, TEMP tmp2, KILL ctr, KILL cr0); + match(Set result (CountPositives ary1 len)); + effect(TEMP_DEF result, TEMP tmp1, TEMP tmp2, KILL ctr, KILL cr0); ins_cost(300); - format %{ "has negatives byte[] $ary1,$len -> $result \t// KILL $tmp1, $tmp2" %} + format %{ "count positives byte[] $ary1,$len -> $result \t// KILL $tmp1, $tmp2" %} ins_encode %{ - __ has_negatives($ary1$$Register, $len$$Register, $result$$Register, - $tmp1$$Register, $tmp2$$Register); + __ count_positives($ary1$$Register, $len$$Register, $result$$Register, + $tmp1$$Register, $tmp2$$Register); %} ins_pipe(pipe_class_default); %} diff --git a/src/hotspot/cpu/s390/c2_MacroAssembler_s390.cpp b/src/hotspot/cpu/s390/c2_MacroAssembler_s390.cpp index 04a6b88052c99cf11b4397061af77f5abd28888a..6fac285f738ace567bf016f244d59e68031db260 100644 --- a/src/hotspot/cpu/s390/c2_MacroAssembler_s390.cpp +++ b/src/hotspot/cpu/s390/c2_MacroAssembler_s390.cpp @@ -823,52 +823,64 @@ unsigned int C2_MacroAssembler::string_inflate_const(Register src, Register dst, return offset() - block_start; } -// Kills src. -unsigned int C2_MacroAssembler::has_negatives(Register result, Register src, Register cnt, - Register odd_reg, Register even_reg, Register tmp) { - int block_start = offset(); - Label Lloop1, Lloop2, Lslow, Lnotfound, Ldone; - const Register addr = src, mask = tmp; - - BLOCK_COMMENT("has_negatives {"); - - z_llgfr(Z_R1, cnt); // Number of bytes to read. (Must be a positive simm32.) - z_llilf(mask, 0x80808080); - z_lhi(result, 1); // Assume true. - // Last possible addr for fast loop. - z_lay(odd_reg, -16, Z_R1, src); - z_chi(cnt, 16); - z_brl(Lslow); - - // ind1: index, even_reg: index increment, odd_reg: index limit - z_iihf(mask, 0x80808080); - z_lghi(even_reg, 16); - - bind(Lloop1); // 16 bytes per iteration. - z_lg(Z_R0, Address(addr)); - z_lg(Z_R1, Address(addr, 8)); - z_ogr(Z_R0, Z_R1); - z_ngr(Z_R0, mask); - z_brne(Ldone); // If found return 1. - z_brxlg(addr, even_reg, Lloop1); - - bind(Lslow); - z_aghi(odd_reg, 16-1); // Last possible addr for slow loop. - z_lghi(even_reg, 1); - z_cgr(addr, odd_reg); - z_brh(Lnotfound); - - bind(Lloop2); // 1 byte per iteration. - z_cli(Address(addr), 0x80); - z_brnl(Ldone); // If found return 1. - z_brxlg(addr, even_reg, Lloop2); - - bind(Lnotfound); - z_lhi(result, 0); - - bind(Ldone); - - BLOCK_COMMENT("} has_negatives"); +// Returns the number of non-negative bytes (aka US-ASCII characters) found +// before the first negative byte is encountered. +unsigned int C2_MacroAssembler::count_positives(Register result, Register src, Register cnt, Register tmp) { + const unsigned int block_start = offset(); + const unsigned int byte_mask = 0x80; + const unsigned int twobyte_mask = byte_mask<<8 | byte_mask; + const unsigned int unroll_factor = 16; + const unsigned int log_unroll_factor = exact_log2(unroll_factor); + Register pos = src; // current position in src array, restored at end + Register ctr = result; // loop counter, result value + Register mask = tmp; // holds the sign detection mask + Label unrolledLoop, unrolledDone, byteLoop, allDone; + + assert_different_registers(result, src, cnt, tmp); + + BLOCK_COMMENT("count_positives {"); + + lgr_if_needed(pos, src); // current position in src array + z_srak(ctr, cnt, log_unroll_factor); // # iterations of unrolled loop + z_brnh(unrolledDone); // array too short for unrolled loop + + z_iilf(mask, twobyte_mask<<16 | twobyte_mask); + z_iihf(mask, twobyte_mask<<16 | twobyte_mask); + + bind(unrolledLoop); + z_lmg(Z_R0, Z_R1, 0, pos); + z_ogr(Z_R0, Z_R1); + z_ngr(Z_R0, mask); + z_brne(unrolledDone); // There is a negative byte somewhere. + // ctr and pos are not updated yet -> + // delegate finding correct pos to byteLoop. + add2reg(pos, unroll_factor); + z_brct(ctr, unrolledLoop); + + // Once we arrive here, we have to examine at most (unroll_factor - 1) bytes more. + // We then either have reached the end of the array or we hit a negative byte. + bind(unrolledDone); + z_sll(ctr, log_unroll_factor); // calculate # bytes not processed by unrolled loop + // > 0 only if a negative byte was found + z_lr(Z_R0, cnt); // calculate remainder bytes + z_nilf(Z_R0, unroll_factor - 1); + z_ar(ctr, Z_R0); // remaining bytes + z_brnh(allDone); // shortcut if nothing left to do + + bind(byteLoop); + z_cli(0, pos, byte_mask); // unsigned comparison! byte@pos must be smaller that byte_mask + z_brnl(allDone); // negative byte found. + + add2reg(pos, 1); + z_brct(ctr, byteLoop); + + bind(allDone); + + z_srk(ctr, cnt, ctr); // # bytes actually processed (= cnt or index of first negative byte) + z_sgfr(pos, ctr); // restore src + z_lgfr(result, ctr); // unnecessary. Only there to be sure the high word has a defined state. + + BLOCK_COMMENT("} count_positives"); return offset() - block_start; } diff --git a/src/hotspot/cpu/s390/c2_MacroAssembler_s390.hpp b/src/hotspot/cpu/s390/c2_MacroAssembler_s390.hpp index a6c9865649522d807d91c3255daa05e9c04ad865..a502e41ee08ee12ca3f4af48dbfe7b37a59a5b4f 100644 --- a/src/hotspot/cpu/s390/c2_MacroAssembler_s390.hpp +++ b/src/hotspot/cpu/s390/c2_MacroAssembler_s390.hpp @@ -57,9 +57,7 @@ // len is signed int. Counts # characters, not bytes. unsigned int string_inflate_const(Register src, Register dst, Register tmp, int len); - // Kills src. - unsigned int has_negatives(Register result, Register src, Register cnt, - Register odd_reg, Register even_reg, Register tmp); + unsigned int count_positives(Register result, Register src, Register cnt, Register tmp); unsigned int string_compare(Register str1, Register str2, Register cnt1, Register cnt2, Register odd_reg, Register even_reg, Register result, int ae); diff --git a/src/hotspot/cpu/s390/frame_s390.inline.hpp b/src/hotspot/cpu/s390/frame_s390.inline.hpp index d8a4395d8cad82800bda84422c6621b6c339c3f3..5574e6384e2218d99dfc7d26a6b6f303e193230c 100644 --- a/src/hotspot/cpu/s390/frame_s390.inline.hpp +++ b/src/hotspot/cpu/s390/frame_s390.inline.hpp @@ -155,6 +155,10 @@ inline intptr_t* frame::link() const { return (intptr_t*) callers_abi()->callers_sp; } +inline intptr_t* frame::link_or_null() const { + return link(); +} + inline intptr_t** frame::interpreter_frame_locals_addr() const { return (intptr_t**) &(ijava_state()->locals); } diff --git a/src/hotspot/cpu/s390/matcher_s390.hpp b/src/hotspot/cpu/s390/matcher_s390.hpp index ac55bd84dff10a5f79b3ae1376c31a37e0351d21..5c56ec5373b7d751e98c614ac6c3b192eb34fecd 100644 --- a/src/hotspot/cpu/s390/matcher_s390.hpp +++ b/src/hotspot/cpu/s390/matcher_s390.hpp @@ -153,4 +153,9 @@ // Implements a variant of EncodeISOArrayNode that encode ASCII only static const bool supports_encode_ascii_array = true; + // Returns pre-selection estimated cost of a vector operation. + static int vector_op_pre_select_sz_estimate(int vopc, BasicType ety, int vlen) { + return 0; + } + #endif // CPU_S390_MATCHER_S390_HPP diff --git a/src/hotspot/cpu/s390/s390.ad b/src/hotspot/cpu/s390/s390.ad index 74ad8ef40d31cfd15d7b7091e290487e5e2e6785..d13afd1c8b4f95db6904005ef5af208dacfde00a 100644 --- a/src/hotspot/cpu/s390/s390.ad +++ b/src/hotspot/cpu/s390/s390.ad @@ -10273,14 +10273,13 @@ instruct string_inflate_const(Universe dummy, iRegP src, iRegP dst, iRegI tmp, i %} // StringCoding.java intrinsics -instruct has_negatives(rarg5RegP ary1, iRegI len, iRegI result, roddRegI oddReg, revenRegI evenReg, iRegI tmp, flagsReg cr) %{ - match(Set result (HasNegatives ary1 len)); - effect(TEMP_DEF result, USE_KILL ary1, TEMP oddReg, TEMP evenReg, TEMP tmp, KILL cr); // R0, R1 are killed, too. +instruct count_positives(iRegP ary1, iRegI len, iRegI result, iRegI tmp, flagsReg cr) %{ + match(Set result (CountPositives ary1 len)); + effect(TEMP_DEF result, TEMP tmp, KILL cr); // R0, R1 are killed, too. ins_cost(300); - format %{ "has negatives byte[] $ary1($len) -> $result" %} + format %{ "count positives byte[] $ary1($len) -> $result" %} ins_encode %{ - __ has_negatives($result$$Register, $ary1$$Register, $len$$Register, - $oddReg$$Register, $evenReg$$Register, $tmp$$Register); + __ count_positives($result$$Register, $ary1$$Register, $len$$Register, $tmp$$Register); %} ins_pipe(pipe_class_dummy); %} diff --git a/src/hotspot/cpu/x86/assembler_x86.cpp b/src/hotspot/cpu/x86/assembler_x86.cpp index e9652fa04b24f55e4ed48a4239f860db14aee3b9..3505e081d38f2484c2fd915ae39d003dbd8c6278 100644 --- a/src/hotspot/cpu/x86/assembler_x86.cpp +++ b/src/hotspot/cpu/x86/assembler_x86.cpp @@ -300,12 +300,24 @@ void Assembler::emit_arith_b(int op1, int op2, Register dst, int imm8) { void Assembler::emit_arith(int op1, int op2, Register dst, int32_t imm32) { assert(isByte(op1) && isByte(op2), "wrong opcode"); - assert((op1 & 0x01) == 1, "should be 32bit operation"); - assert((op1 & 0x02) == 0, "sign-extension bit should not be set"); + assert(op1 == 0x81, "Unexpected opcode"); if (is8bit(imm32)) { emit_int24(op1 | 0x02, // set sign bit op2 | encode(dst), imm32 & 0xFF); + } else if (dst == rax) { + switch (op2) { + case 0xD0: emit_int8(0x15); break; // adc + case 0xC0: emit_int8(0x05); break; // add + case 0xE0: emit_int8(0x25); break; // and + case 0xF8: emit_int8(0x3D); break; // cmp + case 0xC8: emit_int8(0x0D); break; // or + case 0xD8: emit_int8(0x1D); break; // sbb + case 0xE8: emit_int8(0x2D); break; // sub + case 0xF0: emit_int8(0x35); break; // xor + default: ShouldNotReachHere(); + } + emit_int32(imm32); } else { emit_int16(op1, (op2 | encode(dst))); emit_int32(imm32); @@ -929,6 +941,16 @@ address Assembler::locate_operand(address inst, WhichOperand which) { tail_size = 1; break; + case 0x15: // adc rax, #32 + case 0x05: // add rax, #32 + case 0x25: // and rax, #32 + case 0x3D: // cmp rax, #32 + case 0x0D: // or rax, #32 + case 0x1D: // sbb rax, #32 + case 0x2D: // sub rax, #32 + case 0x35: // xor rax, #32 + return which == end_pc_operand ? ip + 4 : ip; + case 0x9B: switch (0xFF & *ip++) { case 0xD9: // fnstcw a @@ -954,6 +976,11 @@ address Assembler::locate_operand(address inst, WhichOperand which) { debug_only(has_disp32 = true); // has both kinds of operands! break; + case 0xA8: // testb rax, #8 + return which == end_pc_operand ? ip + 1 : ip; + case 0xA9: // testl/testq rax, #32 + return which == end_pc_operand ? ip + 4 : ip; + case 0xC1: // sal a, #8; sar a, #8; shl a, #8; shr a, #8 case 0xC6: // movb a, #8 case 0x80: // cmpb a, #8 @@ -1683,12 +1710,6 @@ void Assembler::cmpl(Address dst, int32_t imm32) { emit_int32(imm32); } -void Assembler::cmp(Register dst, int32_t imm32) { - prefix(dst); - emit_int8((unsigned char)0x3D); - emit_int32(imm32); -} - void Assembler::cmpl(Register dst, int32_t imm32) { prefix(dst); emit_arith(0x81, 0xF8, dst, imm32); @@ -2389,10 +2410,7 @@ void Assembler::ldmxcsr( Address src) { void Assembler::leal(Register dst, Address src) { InstructionMark im(this); -#ifdef _LP64 - emit_int8(0x67); // addr32 prefix(src, dst); -#endif // LP64 emit_int8((unsigned char)0x8D); emit_operand(dst, src); } @@ -5775,8 +5793,13 @@ void Assembler::subss(XMMRegister dst, Address src) { void Assembler::testb(Register dst, int imm8) { NOT_LP64(assert(dst->has_byte_register(), "must have byte register")); - (void) prefix_and_encode(dst->encoding(), true); - emit_arith_b(0xF6, 0xC0, dst, imm8); + if (dst == rax) { + emit_int8((unsigned char)0xA8); + emit_int8(imm8); + } else { + (void) prefix_and_encode(dst->encoding(), true); + emit_arith_b(0xF6, 0xC0, dst, imm8); + } } void Assembler::testb(Address dst, int imm8) { @@ -5787,14 +5810,34 @@ void Assembler::testb(Address dst, int imm8) { emit_int8(imm8); } +void Assembler::testl(Address dst, int32_t imm32) { + if (imm32 >= 0 && is8bit(imm32)) { + testb(dst, imm32); + return; + } + InstructionMark im(this); + emit_int8((unsigned char)0xF7); + emit_operand(as_Register(0), dst); + emit_int32(imm32); +} + void Assembler::testl(Register dst, int32_t imm32) { + if (imm32 >= 0 && is8bit(imm32) && dst->has_byte_register()) { + testb(dst, imm32); + return; + } // not using emit_arith because test // doesn't support sign-extension of // 8bit operands - int encode = dst->encoding(); - encode = prefix_and_encode(encode); - emit_int16((unsigned char)0xF7, (0xC0 | encode)); - emit_int32(imm32); + if (dst == rax) { + emit_int8((unsigned char)0xA9); + emit_int32(imm32); + } else { + int encode = dst->encoding(); + encode = prefix_and_encode(encode); + emit_int16((unsigned char)0xF7, (0xC0 | encode)); + emit_int32(imm32); + } } void Assembler::testl(Register dst, Register src) { @@ -8317,8 +8360,28 @@ void Assembler::vpbroadcastw(XMMRegister dst, Address src, int vector_len) { emit_operand(dst, src); } -// xmm/mem sourced byte/word/dword/qword replicate +void Assembler::vpsadbw(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len) { + assert(UseAVX > 0, "requires some form of AVX"); + InstructionAttr attributes(vector_len, /* vex_w */ false, /* legacy_mode */ _legacy_mode_bw, /* no_mask_reg */ true, /* uses_vl */ true); + int encode = vex_prefix_and_encode(dst->encoding(), nds->encoding(), src->encoding(), VEX_SIMD_66, VEX_OPCODE_0F, &attributes); + emit_int16((unsigned char)0xF6, (0xC0 | encode)); +} + +void Assembler::vpunpckhdq(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len) { + assert(UseAVX > 0, "requires some form of AVX"); + InstructionAttr attributes(vector_len, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ true); + int encode = vex_prefix_and_encode(dst->encoding(), nds->encoding(), src->encoding(), VEX_SIMD_66, VEX_OPCODE_0F, &attributes); + emit_int16(0x6A, (0xC0 | encode)); +} + +void Assembler::vpunpckldq(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len) { + assert(UseAVX > 0, "requires some form of AVX"); + InstructionAttr attributes(vector_len, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ true); + int encode = vex_prefix_and_encode(dst->encoding(), nds->encoding(), src->encoding(), VEX_SIMD_66, VEX_OPCODE_0F, &attributes); + emit_int16(0x62, (0xC0 | encode)); +} +// xmm/mem sourced byte/word/dword/qword replicate void Assembler::evpaddb(XMMRegister dst, KRegister mask, XMMRegister nds, XMMRegister src, bool merge, int vector_len) { assert(VM_Version::supports_avx512bw() && (vector_len == AVX_512bit || VM_Version::supports_avx512vl()), ""); InstructionAttr attributes(vector_len, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ false,/* uses_vl */ true); @@ -9864,12 +9927,12 @@ void Assembler::vpbroadcastq(XMMRegister dst, Address src, int vector_len) { void Assembler::evbroadcasti32x4(XMMRegister dst, Address src, int vector_len) { assert(vector_len != Assembler::AVX_128bit, ""); - assert(VM_Version::supports_avx512dq(), ""); + assert(VM_Version::supports_evex(), ""); assert(dst != xnoreg, "sanity"); InstructionMark im(this); InstructionAttr attributes(vector_len, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ true); attributes.set_rex_vex_w_reverted(); - attributes.set_address_attributes(/* tuple_type */ EVEX_T2, /* input_size_in_bits */ EVEX_64bit); + attributes.set_address_attributes(/* tuple_type */ EVEX_T4, /* input_size_in_bits */ EVEX_32bit); // swap src<->dst for encoding vex_prefix(src, 0, dst->encoding(), VEX_SIMD_66, VEX_OPCODE_0F_38, &attributes); emit_int8(0x5A); @@ -12993,6 +13056,10 @@ void Assembler::subq(Register dst, Register src) { } void Assembler::testq(Address dst, int32_t imm32) { + if (imm32 >= 0) { + testl(dst, imm32); + return; + } InstructionMark im(this); emit_int16(get_prefixq(dst), (unsigned char)0xF7); emit_operand(as_Register(0), dst); @@ -13000,13 +13067,23 @@ void Assembler::testq(Address dst, int32_t imm32) { } void Assembler::testq(Register dst, int32_t imm32) { + if (imm32 >= 0) { + testl(dst, imm32); + return; + } // not using emit_arith because test // doesn't support sign-extension of // 8bit operands - int encode = dst->encoding(); - encode = prefixq_and_encode(encode); - emit_int16((unsigned char)0xF7, (0xC0 | encode)); - emit_int32(imm32); + if (dst == rax) { + prefix(REX_W); + emit_int8((unsigned char)0xA9); + emit_int32(imm32); + } else { + int encode = dst->encoding(); + encode = prefixq_and_encode(encode); + emit_int16((unsigned char)0xF7, (0xC0 | encode)); + emit_int32(imm32); + } } void Assembler::testq(Register dst, Register src) { diff --git a/src/hotspot/cpu/x86/assembler_x86.hpp b/src/hotspot/cpu/x86/assembler_x86.hpp index f21dd901c5d8d237df8b1d1ab37d896a38a30e37..7141e4b96c4141f2184cab62bbff2428313bf649 100644 --- a/src/hotspot/cpu/x86/assembler_x86.hpp +++ b/src/hotspot/cpu/x86/assembler_x86.hpp @@ -1081,15 +1081,12 @@ private: void cmpb(Address dst, int imm8); void cmpl(Address dst, int32_t imm32); - - void cmp(Register dst, int32_t imm32); void cmpl(Register dst, int32_t imm32); void cmpl(Register dst, Register src); void cmpl(Register dst, Address src); void cmpq(Address dst, int32_t imm32); void cmpq(Address dst, Register src); - void cmpq(Register dst, int32_t imm32); void cmpq(Register dst, Register src); void cmpq(Register dst, Address src); @@ -1933,10 +1930,17 @@ private: // Interleave Low Doublewords void punpckldq(XMMRegister dst, XMMRegister src); void punpckldq(XMMRegister dst, Address src); + void vpunpckldq(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len); + + // Interleave High Doublewords + void vpunpckhdq(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len); // Interleave Low Quadwords void punpcklqdq(XMMRegister dst, XMMRegister src); + // Vector sum of absolute difference. + void vpsadbw(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len); + #ifndef _LP64 // no 32bit push/pop on amd64 void pushl(Address src); #endif @@ -2092,9 +2096,10 @@ private: void subss(XMMRegister dst, Address src); void subss(XMMRegister dst, XMMRegister src); - void testb(Register dst, int imm8); void testb(Address dst, int imm8); + void testb(Register dst, int imm8); + void testl(Address dst, int32_t imm32); void testl(Register dst, int32_t imm32); void testl(Register dst, Register src); void testl(Register dst, Address src); diff --git a/src/hotspot/cpu/x86/c2_MacroAssembler_x86.cpp b/src/hotspot/cpu/x86/c2_MacroAssembler_x86.cpp index 400bcec45e2a01ac946c2e84f95e0e56cb6efd77..6d8b9101303508409fa4a8b2b01770670ed69fea 100644 --- a/src/hotspot/cpu/x86/c2_MacroAssembler_x86.cpp +++ b/src/hotspot/cpu/x86/c2_MacroAssembler_x86.cpp @@ -3374,18 +3374,19 @@ void C2_MacroAssembler::string_compare(Register str1, Register str2, } // Search for Non-ASCII character (Negative byte value) in a byte array, -// return true if it has any and false otherwise. +// return the index of the first such character, otherwise the length +// of the array segment searched. // ..\jdk\src\java.base\share\classes\java\lang\StringCoding.java // @IntrinsicCandidate -// private static boolean hasNegatives(byte[] ba, int off, int len) { +// public static int countPositives(byte[] ba, int off, int len) { // for (int i = off; i < off + len; i++) { // if (ba[i] < 0) { -// return true; +// return i - off; // } // } -// return false; +// return len; // } -void C2_MacroAssembler::has_negatives(Register ary1, Register len, +void C2_MacroAssembler::count_positives(Register ary1, Register len, Register result, Register tmp1, XMMRegister vec1, XMMRegister vec2, KRegister mask1, KRegister mask2) { // rsi: byte array @@ -3394,17 +3395,18 @@ void C2_MacroAssembler::has_negatives(Register ary1, Register len, ShortBranchVerifier sbv(this); assert_different_registers(ary1, len, result, tmp1); assert_different_registers(vec1, vec2); - Label TRUE_LABEL, FALSE_LABEL, DONE, COMPARE_CHAR, COMPARE_VECTORS, COMPARE_BYTE; + Label ADJUST, TAIL_ADJUST, DONE, TAIL_START, CHAR_ADJUST, COMPARE_CHAR, COMPARE_VECTORS, COMPARE_BYTE; + movl(result, len); // copy // len == 0 testl(len, len); - jcc(Assembler::zero, FALSE_LABEL); + jcc(Assembler::zero, DONE); if ((AVX3Threshold == 0) && (UseAVX > 2) && // AVX512 VM_Version::supports_avx512vlbw() && VM_Version::supports_bmi2()) { - Label test_64_loop, test_tail; + Label test_64_loop, test_tail, BREAK_LOOP; Register tmp3_aliased = len; movl(tmp1, len); @@ -3421,16 +3423,15 @@ void C2_MacroAssembler::has_negatives(Register ary1, Register len, // Check whether our 64 elements of size byte contain negatives evpcmpgtb(mask1, vec2, Address(ary1, len, Address::times_1), Assembler::AVX_512bit); kortestql(mask1, mask1); - jcc(Assembler::notZero, TRUE_LABEL); + jcc(Assembler::notZero, BREAK_LOOP); addptr(len, 64); jccb(Assembler::notZero, test_64_loop); - bind(test_tail); // bail out when there is nothing to be done testl(tmp1, -1); - jcc(Assembler::zero, FALSE_LABEL); + jcc(Assembler::zero, DONE); // ~(~0 << len) applied up to two times (for 32-bit scenario) #ifdef _LP64 @@ -3467,21 +3468,30 @@ void C2_MacroAssembler::has_negatives(Register ary1, Register len, #endif evpcmpgtb(mask1, mask2, vec2, Address(ary1, 0), Assembler::AVX_512bit); ktestq(mask1, mask2); - jcc(Assembler::notZero, TRUE_LABEL); + jcc(Assembler::zero, DONE); - jmp(FALSE_LABEL); + bind(BREAK_LOOP); + // At least one byte in the last 64 bytes is negative. + // Set up to look at the last 64 bytes as if they were a tail + lea(ary1, Address(ary1, len, Address::times_1)); + addptr(result, len); + // Ignore the very last byte: if all others are positive, + // it must be negative, so we can skip right to the 2+1 byte + // end comparison at this point + orl(result, 63); + movl(len, 63); + // Fallthru to tail compare } else { - movl(result, len); // copy if (UseAVX >= 2 && UseSSE >= 2) { // With AVX2, use 32-byte vector compare - Label COMPARE_WIDE_VECTORS, COMPARE_TAIL; + Label COMPARE_WIDE_VECTORS, BREAK_LOOP; // Compare 32-byte vectors - andl(result, 0x0000001f); // tail count (in bytes) - andl(len, 0xffffffe0); // vector count (in bytes) - jccb(Assembler::zero, COMPARE_TAIL); + testl(len, 0xffffffe0); // vector count (in bytes) + jccb(Assembler::zero, TAIL_START); + andl(len, 0xffffffe0); lea(ary1, Address(ary1, len, Address::times_1)); negptr(len); @@ -3492,30 +3502,42 @@ void C2_MacroAssembler::has_negatives(Register ary1, Register len, bind(COMPARE_WIDE_VECTORS); vmovdqu(vec1, Address(ary1, len, Address::times_1)); vptest(vec1, vec2); - jccb(Assembler::notZero, TRUE_LABEL); + jccb(Assembler::notZero, BREAK_LOOP); addptr(len, 32); - jcc(Assembler::notZero, COMPARE_WIDE_VECTORS); + jccb(Assembler::notZero, COMPARE_WIDE_VECTORS); - testl(result, result); - jccb(Assembler::zero, FALSE_LABEL); + testl(result, 0x0000001f); // any bytes remaining? + jcc(Assembler::zero, DONE); - vmovdqu(vec1, Address(ary1, result, Address::times_1, -32)); + // Quick test using the already prepared vector mask + movl(len, result); + andl(len, 0x0000001f); + vmovdqu(vec1, Address(ary1, len, Address::times_1, -32)); vptest(vec1, vec2); - jccb(Assembler::notZero, TRUE_LABEL); - jmpb(FALSE_LABEL); + jcc(Assembler::zero, DONE); + // There are zeros, jump to the tail to determine exactly where + jmpb(TAIL_START); - bind(COMPARE_TAIL); // len is zero - movl(len, result); + bind(BREAK_LOOP); + // At least one byte in the last 32-byte vector is negative. + // Set up to look at the last 32 bytes as if they were a tail + lea(ary1, Address(ary1, len, Address::times_1)); + addptr(result, len); + // Ignore the very last byte: if all others are positive, + // it must be negative, so we can skip right to the 2+1 byte + // end comparison at this point + orl(result, 31); + movl(len, 31); // Fallthru to tail compare } else if (UseSSE42Intrinsics) { // With SSE4.2, use double quad vector compare - Label COMPARE_WIDE_VECTORS, COMPARE_TAIL; + Label COMPARE_WIDE_VECTORS, BREAK_LOOP; // Compare 16-byte vectors - andl(result, 0x0000000f); // tail count (in bytes) - andl(len, 0xfffffff0); // vector count (in bytes) - jcc(Assembler::zero, COMPARE_TAIL); + testl(len, 0xfffffff0); // vector count (in bytes) + jcc(Assembler::zero, TAIL_START); + andl(len, 0xfffffff0); lea(ary1, Address(ary1, len, Address::times_1)); negptr(len); @@ -3526,23 +3548,36 @@ void C2_MacroAssembler::has_negatives(Register ary1, Register len, bind(COMPARE_WIDE_VECTORS); movdqu(vec1, Address(ary1, len, Address::times_1)); ptest(vec1, vec2); - jcc(Assembler::notZero, TRUE_LABEL); + jccb(Assembler::notZero, BREAK_LOOP); addptr(len, 16); - jcc(Assembler::notZero, COMPARE_WIDE_VECTORS); + jccb(Assembler::notZero, COMPARE_WIDE_VECTORS); - testl(result, result); - jcc(Assembler::zero, FALSE_LABEL); + testl(result, 0x0000000f); // len is zero, any bytes remaining? + jcc(Assembler::zero, DONE); - movdqu(vec1, Address(ary1, result, Address::times_1, -16)); + // Quick test using the already prepared vector mask + movl(len, result); + andl(len, 0x0000000f); // tail count (in bytes) + movdqu(vec1, Address(ary1, len, Address::times_1, -16)); ptest(vec1, vec2); - jccb(Assembler::notZero, TRUE_LABEL); - jmpb(FALSE_LABEL); + jcc(Assembler::zero, DONE); + jmpb(TAIL_START); - bind(COMPARE_TAIL); // len is zero - movl(len, result); + bind(BREAK_LOOP); + // At least one byte in the last 16-byte vector is negative. + // Set up and look at the last 16 bytes as if they were a tail + lea(ary1, Address(ary1, len, Address::times_1)); + addptr(result, len); + // Ignore the very last byte: if all others are positive, + // it must be negative, so we can skip right to the 2+1 byte + // end comparison at this point + orl(result, 15); + movl(len, 15); // Fallthru to tail compare } } + + bind(TAIL_START); // Compare 4-byte vectors andl(len, 0xfffffffc); // vector count (in bytes) jccb(Assembler::zero, COMPARE_CHAR); @@ -3553,34 +3588,45 @@ void C2_MacroAssembler::has_negatives(Register ary1, Register len, bind(COMPARE_VECTORS); movl(tmp1, Address(ary1, len, Address::times_1)); andl(tmp1, 0x80808080); - jccb(Assembler::notZero, TRUE_LABEL); + jccb(Assembler::notZero, TAIL_ADJUST); addptr(len, 4); - jcc(Assembler::notZero, COMPARE_VECTORS); + jccb(Assembler::notZero, COMPARE_VECTORS); - // Compare trailing char (final 2 bytes), if any + // Compare trailing char (final 2-3 bytes), if any bind(COMPARE_CHAR); + testl(result, 0x2); // tail char jccb(Assembler::zero, COMPARE_BYTE); load_unsigned_short(tmp1, Address(ary1, 0)); andl(tmp1, 0x00008080); - jccb(Assembler::notZero, TRUE_LABEL); - subptr(result, 2); + jccb(Assembler::notZero, CHAR_ADJUST); lea(ary1, Address(ary1, 2)); bind(COMPARE_BYTE); testl(result, 0x1); // tail byte - jccb(Assembler::zero, FALSE_LABEL); + jccb(Assembler::zero, DONE); load_unsigned_byte(tmp1, Address(ary1, 0)); - andl(tmp1, 0x00000080); - jccb(Assembler::notEqual, TRUE_LABEL); - jmpb(FALSE_LABEL); - - bind(TRUE_LABEL); - movl(result, 1); // return true + testl(tmp1, 0x00000080); + jccb(Assembler::zero, DONE); + subptr(result, 1); jmpb(DONE); - bind(FALSE_LABEL); - xorl(result, result); // return false + bind(TAIL_ADJUST); + // there are negative bits in the last 4 byte block. + // Adjust result and check the next three bytes + addptr(result, len); + orl(result, 3); + lea(ary1, Address(ary1, len, Address::times_1)); + jmpb(COMPARE_CHAR); + + bind(CHAR_ADJUST); + // We are looking at a char + optional byte tail, and found that one + // of the bytes in the char is negative. Adjust the result, check the + // first byte and readjust if needed. + andl(result, 0xfffffffc); + testl(tmp1, 0x00000080); // little-endian, so lowest byte comes first + jccb(Assembler::notZero, DONE); + addptr(result, 1); // That's it bind(DONE); @@ -3590,6 +3636,7 @@ void C2_MacroAssembler::has_negatives(Register ary1, Register len, vpxor(vec2, vec2); } } + // Compare char[] or byte[] arrays aligned to 4 bytes or substrings. void C2_MacroAssembler::arrays_equals(bool is_array_equ, Register ary1, Register ary2, Register limit, Register result, Register chr, @@ -4321,6 +4368,94 @@ void C2_MacroAssembler::vector_maskall_operation(KRegister dst, Register src, in } } + +// +// Following is lookup table based popcount computation algorithm:- +// Index Bit set count +// [ 0000 -> 0, +// 0001 -> 1, +// 0010 -> 1, +// 0011 -> 2, +// 0100 -> 1, +// 0101 -> 2, +// 0110 -> 2, +// 0111 -> 3, +// 1000 -> 1, +// 1001 -> 2, +// 1010 -> 3, +// 1011 -> 3, +// 1100 -> 2, +// 1101 -> 3, +// 1111 -> 4 ] +// a. Count the number of 1s in 4 LSB bits of each byte. These bits are used as +// shuffle indices for lookup table access. +// b. Right shift each byte of vector lane by 4 positions. +// c. Count the number of 1s in 4 MSB bits each byte. These bits are used as +// shuffle indices for lookup table access. +// d. Add the bitset count of upper and lower 4 bits of each byte. +// e. Unpack double words to quad words and compute sum of absolute difference of bitset +// count of all the bytes of a quadword. +// f. Perform step e. for upper 128bit vector lane. +// g. Pack the bitset count of quadwords back to double word. +// h. Unpacking and packing operations are not needed for 64bit vector lane. +void C2_MacroAssembler::vector_popcount_int(XMMRegister dst, XMMRegister src, XMMRegister xtmp1, + XMMRegister xtmp2, XMMRegister xtmp3, Register rtmp, + int vec_enc) { + if (VM_Version::supports_avx512_vpopcntdq()) { + vpopcntd(dst, src, vec_enc); + } else { + assert((vec_enc == Assembler::AVX_512bit && VM_Version::supports_avx512bw()) || VM_Version::supports_avx2(), ""); + movl(rtmp, 0x0F0F0F0F); + movdl(xtmp1, rtmp); + vpbroadcastd(xtmp1, xtmp1, vec_enc); + if (Assembler::AVX_512bit == vec_enc) { + evmovdqul(xtmp2, k0, ExternalAddress(StubRoutines::x86::vector_popcount_lut()), false, vec_enc, rtmp); + } else { + vmovdqu(xtmp2, ExternalAddress(StubRoutines::x86::vector_popcount_lut()), rtmp); + } + vpand(xtmp3, src, xtmp1, vec_enc); + vpshufb(xtmp3, xtmp2, xtmp3, vec_enc); + vpsrlw(dst, src, 4, vec_enc); + vpand(dst, dst, xtmp1, vec_enc); + vpshufb(dst, xtmp2, dst, vec_enc); + vpaddb(xtmp3, dst, xtmp3, vec_enc); + vpxor(xtmp1, xtmp1, xtmp1, vec_enc); + vpunpckhdq(dst, xtmp3, xtmp1, vec_enc); + vpsadbw(dst, dst, xtmp1, vec_enc); + vpunpckldq(xtmp2, xtmp3, xtmp1, vec_enc); + vpsadbw(xtmp2, xtmp2, xtmp1, vec_enc); + vpackuswb(dst, xtmp2, dst, vec_enc); + } +} + +void C2_MacroAssembler::vector_popcount_long(XMMRegister dst, XMMRegister src, XMMRegister xtmp1, + XMMRegister xtmp2, XMMRegister xtmp3, Register rtmp, + int vec_enc) { + if (VM_Version::supports_avx512_vpopcntdq()) { + vpopcntq(dst, src, vec_enc); + } else if (vec_enc == Assembler::AVX_512bit) { + assert(VM_Version::supports_avx512bw(), ""); + movl(rtmp, 0x0F0F0F0F); + movdl(xtmp1, rtmp); + vpbroadcastd(xtmp1, xtmp1, vec_enc); + evmovdqul(xtmp2, k0, ExternalAddress(StubRoutines::x86::vector_popcount_lut()), true, vec_enc, rtmp); + vpandq(xtmp3, src, xtmp1, vec_enc); + vpshufb(xtmp3, xtmp2, xtmp3, vec_enc); + vpsrlw(dst, src, 4, vec_enc); + vpandq(dst, dst, xtmp1, vec_enc); + vpshufb(dst, xtmp2, dst, vec_enc); + vpaddb(xtmp3, dst, xtmp3, vec_enc); + vpxorq(xtmp1, xtmp1, xtmp1, vec_enc); + vpsadbw(dst, xtmp3, xtmp1, vec_enc); + } else { + // We do not see any performance benefit of running + // above instruction sequence on 256 bit vector which + // can operate over maximum 4 long elements. + ShouldNotReachHere(); + } + evpmovqd(dst, dst, vec_enc); +} + #ifndef _LP64 void C2_MacroAssembler::vector_maskall_operation32(KRegister dst, Register src, KRegister tmp, int mask_len) { assert(VM_Version::supports_avx512bw(), ""); diff --git a/src/hotspot/cpu/x86/c2_MacroAssembler_x86.hpp b/src/hotspot/cpu/x86/c2_MacroAssembler_x86.hpp index 0e6a381430f2ae087e7a3a4eaa3c592b0a248fd5..5ecdf20700dfb11c584898481acdf48dbd2dfd49 100644 --- a/src/hotspot/cpu/x86/c2_MacroAssembler_x86.hpp +++ b/src/hotspot/cpu/x86/c2_MacroAssembler_x86.hpp @@ -271,11 +271,10 @@ public: XMMRegister vec1, int ae, KRegister mask = knoreg); // Search for Non-ASCII character (Negative byte value) in a byte array, - // return true if it has any and false otherwise. - void has_negatives(Register ary1, Register len, - Register result, Register tmp1, - XMMRegister vec1, XMMRegister vec2, KRegister mask1 = knoreg, KRegister mask2 = knoreg); - + // return index of the first such character, otherwise len. + void count_positives(Register ary1, Register len, + Register result, Register tmp1, + XMMRegister vec1, XMMRegister vec2, KRegister mask1 = knoreg, KRegister mask2 = knoreg); // Compare char[] or byte[] arrays. void arrays_equals(bool is_array_equ, Register ary1, Register ary2, Register limit, Register result, Register chr, @@ -317,4 +316,12 @@ public: void evpternlog(XMMRegister dst, int func, KRegister mask, XMMRegister src2, Address src3, bool merge, BasicType bt, int vlen_enc); + void vector_popcount_int(XMMRegister dst, XMMRegister src, XMMRegister xtmp1, + XMMRegister xtmp2, XMMRegister xtmp3, Register rtmp, + int vec_enc); + + void vector_popcount_long(XMMRegister dst, XMMRegister src, XMMRegister xtmp1, + XMMRegister xtmp2, XMMRegister xtmp3, Register rtmp, + int vec_enc); + #endif // CPU_X86_C2_MACROASSEMBLER_X86_HPP diff --git a/src/hotspot/cpu/x86/copy_x86.hpp b/src/hotspot/cpu/x86/copy_x86.hpp index 74228b57f6c58949af2c1baa041cb899bcfb3fd5..1798e74eb0636f9b16b53beaee83397241f379d8 100644 --- a/src/hotspot/cpu/x86/copy_x86.hpp +++ b/src/hotspot/cpu/x86/copy_x86.hpp @@ -148,22 +148,7 @@ static void pd_disjoint_words(const HeapWord* from, HeapWord* to, size_t count) static void pd_disjoint_words_atomic(const HeapWord* from, HeapWord* to, size_t count) { #ifdef AMD64 - switch (count) { - case 8: to[7] = from[7]; - case 7: to[6] = from[6]; - case 6: to[5] = from[5]; - case 5: to[4] = from[4]; - case 4: to[3] = from[3]; - case 3: to[2] = from[2]; - case 2: to[1] = from[1]; - case 1: to[0] = from[0]; - case 0: break; - default: - while (count-- > 0) { - *to++ = *from++; - } - break; - } + shared_disjoint_words_atomic(from, to, count); #else // pd_disjoint_words is word-atomic in this implementation. pd_disjoint_words(from, to, count); diff --git a/src/hotspot/cpu/x86/frame_x86.inline.hpp b/src/hotspot/cpu/x86/frame_x86.inline.hpp index 733a357d5fe3e7fe9a9e445b64b1ebd4b7c381ea..23072238e16aa3caf798e6f0690f3e5f4ca9ccaf 100644 --- a/src/hotspot/cpu/x86/frame_x86.inline.hpp +++ b/src/hotspot/cpu/x86/frame_x86.inline.hpp @@ -138,10 +138,13 @@ inline intptr_t* frame::id(void) const { return unextended_sp(); } inline bool frame::is_older(intptr_t* id) const { assert(this->id() != NULL && id != NULL, "NULL frame id"); return this->id() > id ; } - - inline intptr_t* frame::link() const { return (intptr_t*) *(intptr_t **)addr_at(link_offset); } +inline intptr_t* frame::link_or_null() const { + intptr_t** ptr = (intptr_t **)addr_at(link_offset); + return os::is_readable_pointer(ptr) ? *ptr : NULL; +} + inline intptr_t* frame::unextended_sp() const { return _unextended_sp; } // Return address: diff --git a/src/hotspot/cpu/x86/gc/g1/g1BarrierSetAssembler_x86.cpp b/src/hotspot/cpu/x86/gc/g1/g1BarrierSetAssembler_x86.cpp index 6525b13c5c253e54b3b2a4bce288a506ed582304..475a92d0f43a5264b37765917bb07f7c764f8c1e 100644 --- a/src/hotspot/cpu/x86/gc/g1/g1BarrierSetAssembler_x86.cpp +++ b/src/hotspot/cpu/x86/gc/g1/g1BarrierSetAssembler_x86.cpp @@ -67,7 +67,7 @@ void G1BarrierSetAssembler::gen_write_ref_array_pre_barrier(MacroAssembler* masm __ jcc(Assembler::equal, filtered); - __ pusha(); // push registers + __ push_call_clobbered_registers(false /* save_fpu */); #ifdef _LP64 if (count == c_rarg0) { if (addr == c_rarg1) { @@ -90,7 +90,7 @@ void G1BarrierSetAssembler::gen_write_ref_array_pre_barrier(MacroAssembler* masm __ call_VM_leaf(CAST_FROM_FN_PTR(address, G1BarrierSetRuntime::write_ref_array_pre_oop_entry), addr, count); #endif - __ popa(); + __ pop_call_clobbered_registers(false /* save_fpu */); __ bind(filtered); } @@ -98,7 +98,7 @@ void G1BarrierSetAssembler::gen_write_ref_array_pre_barrier(MacroAssembler* masm void G1BarrierSetAssembler::gen_write_ref_array_post_barrier(MacroAssembler* masm, DecoratorSet decorators, Register addr, Register count, Register tmp) { - __ pusha(); // push registers (overkill) + __ push_call_clobbered_registers(false /* save_fpu */); #ifdef _LP64 if (c_rarg0 == count) { // On win64 c_rarg0 == rcx assert_different_registers(c_rarg1, addr); @@ -114,7 +114,7 @@ void G1BarrierSetAssembler::gen_write_ref_array_post_barrier(MacroAssembler* mas __ call_VM_leaf(CAST_FROM_FN_PTR(address, G1BarrierSetRuntime::write_ref_array_post_entry), addr, count); #endif - __ popa(); + __ pop_call_clobbered_registers(false /* save_fpu */); } void G1BarrierSetAssembler::load_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type, @@ -204,14 +204,15 @@ void G1BarrierSetAssembler::g1_write_barrier_pre(MacroAssembler* masm, __ jmp(done); __ bind(runtime); - // save the live input values - if(tosca_live) __ push(rax); - if (obj != noreg && obj != rax) - __ push(obj); + // Determine and save the live input values + RegSet saved; + if (tosca_live) saved += RegSet::of(rax); + if (obj != noreg && obj != rax) saved += RegSet::of(obj); + if (pre_val != rax) saved += RegSet::of(pre_val); + NOT_LP64( saved += RegSet::of(thread); ) - if (pre_val != rax) - __ push(pre_val); + __ push_set(saved); // Calling the runtime using the regular call_VM_leaf mechanism generates // code (generated by InterpreterMacroAssember::call_VM_leaf_base) @@ -225,8 +226,6 @@ void G1BarrierSetAssembler::g1_write_barrier_pre(MacroAssembler* masm, // So when we do not have have a full interpreter frame on the stack // expand_call should be passed true. - NOT_LP64( __ push(thread); ) - if (expand_call) { LP64_ONLY( assert(pre_val != c_rarg1, "smashed arg"); ) #ifdef _LP64 @@ -244,17 +243,7 @@ void G1BarrierSetAssembler::g1_write_barrier_pre(MacroAssembler* masm, } else { __ call_VM_leaf(CAST_FROM_FN_PTR(address, G1BarrierSetRuntime::write_ref_field_pre_entry), pre_val, thread); } - - NOT_LP64( __ pop(thread); ) - - // save the live input values - if (pre_val != rax) - __ pop(pre_val); - - if (obj != noreg && obj != rax) - __ pop(obj); - - if(tosca_live) __ pop(rax); + __ pop_set(saved); __ bind(done); } @@ -328,21 +317,16 @@ void G1BarrierSetAssembler::g1_write_barrier_post(MacroAssembler* masm, __ bind(runtime); // save the live input values - __ push(store_addr); -#ifdef _LP64 - __ call_VM_leaf(CAST_FROM_FN_PTR(address, G1BarrierSetRuntime::write_ref_field_post_entry), card_addr, r15_thread); -#else - __ push(thread); + RegSet saved = RegSet::of(store_addr NOT_LP64(COMMA thread)); + __ push_set(saved); __ call_VM_leaf(CAST_FROM_FN_PTR(address, G1BarrierSetRuntime::write_ref_field_post_entry), card_addr, thread); - __ pop(thread); -#endif - __ pop(store_addr); + __ pop_set(saved); __ bind(done); } void G1BarrierSetAssembler::oop_store_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type, - Address dst, Register val, Register tmp1, Register tmp2) { + Address dst, Register val, Register tmp1, Register tmp2, Register tmp3) { bool in_heap = (decorators & IN_HEAP) != 0; bool as_normal = (decorators & AS_NORMAL) != 0; assert((decorators & IS_DEST_UNINITIALIZED) == 0, "unsupported"); @@ -350,7 +334,6 @@ void G1BarrierSetAssembler::oop_store_at(MacroAssembler* masm, DecoratorSet deco bool needs_pre_barrier = as_normal; bool needs_post_barrier = val != noreg && in_heap; - Register tmp3 = LP64_ONLY(r8) NOT_LP64(rsi); Register rthread = LP64_ONLY(r15_thread) NOT_LP64(rcx); // flatten object address if needed // We do it regardless of precise because we need the registers @@ -379,7 +362,7 @@ void G1BarrierSetAssembler::oop_store_at(MacroAssembler* masm, DecoratorSet deco false /* expand_call */); } if (val == noreg) { - BarrierSetAssembler::store_at(masm, decorators, type, Address(tmp1, 0), val, noreg, noreg); + BarrierSetAssembler::store_at(masm, decorators, type, Address(tmp1, 0), val, noreg, noreg, noreg); } else { Register new_val = val; if (needs_post_barrier) { @@ -389,7 +372,7 @@ void G1BarrierSetAssembler::oop_store_at(MacroAssembler* masm, DecoratorSet deco __ movptr(new_val, val); } } - BarrierSetAssembler::store_at(masm, decorators, type, Address(tmp1, 0), val, noreg, noreg); + BarrierSetAssembler::store_at(masm, decorators, type, Address(tmp1, 0), val, noreg, noreg, noreg); if (needs_post_barrier) { g1_write_barrier_post(masm /*masm*/, tmp1 /* store_adr */, @@ -496,13 +479,13 @@ void G1BarrierSetAssembler::generate_c1_pre_barrier_runtime_stub(StubAssembler* __ bind(runtime); - __ save_live_registers_no_oop_map(true); + __ push_call_clobbered_registers(); // load the pre-value __ load_parameter(0, rcx); __ call_VM_leaf(CAST_FROM_FN_PTR(address, G1BarrierSetRuntime::write_ref_field_pre_entry), rcx, thread); - __ restore_live_registers(true); + __ pop_call_clobbered_registers(); __ bind(done); @@ -515,9 +498,6 @@ void G1BarrierSetAssembler::generate_c1_pre_barrier_runtime_stub(StubAssembler* void G1BarrierSetAssembler::generate_c1_post_barrier_runtime_stub(StubAssembler* sasm) { __ prologue("g1_post_barrier", false); - // arg0: store_address - Address store_addr(rbp, 2*BytesPerWord); - CardTableBarrierSet* ct = barrier_set_cast(BarrierSet::barrier_set()); @@ -573,12 +553,11 @@ void G1BarrierSetAssembler::generate_c1_post_barrier_runtime_stub(StubAssembler* __ jmp(enqueued); __ bind(runtime); - - __ save_live_registers_no_oop_map(true); + __ push_call_clobbered_registers(); __ call_VM_leaf(CAST_FROM_FN_PTR(address, G1BarrierSetRuntime::write_ref_field_post_entry), card_addr, thread); - __ restore_live_registers(true); + __ pop_call_clobbered_registers(); __ bind(enqueued); __ pop(rdx); diff --git a/src/hotspot/cpu/x86/gc/g1/g1BarrierSetAssembler_x86.hpp b/src/hotspot/cpu/x86/gc/g1/g1BarrierSetAssembler_x86.hpp index 94bbadc7b2b14622e7a168a6641d6615200bfe2f..a5695f5657a4ad6a10ed8fc1687959f6b55f2ecb 100644 --- a/src/hotspot/cpu/x86/gc/g1/g1BarrierSetAssembler_x86.hpp +++ b/src/hotspot/cpu/x86/gc/g1/g1BarrierSetAssembler_x86.hpp @@ -54,7 +54,7 @@ class G1BarrierSetAssembler: public ModRefBarrierSetAssembler { Register tmp2); virtual void oop_store_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type, - Address dst, Register val, Register tmp1, Register tmp2); + Address dst, Register val, Register tmp1, Register tmp2, Register tmp3); public: void gen_pre_barrier_stub(LIR_Assembler* ce, G1PreBarrierStub* stub); diff --git a/src/hotspot/cpu/x86/gc/shared/barrierSetAssembler_x86.cpp b/src/hotspot/cpu/x86/gc/shared/barrierSetAssembler_x86.cpp index 55823bdf217c33b059b7066d38e310fd61056d2d..930926bbb17652308db427ae09242dba1db94451 100644 --- a/src/hotspot/cpu/x86/gc/shared/barrierSetAssembler_x86.cpp +++ b/src/hotspot/cpu/x86/gc/shared/barrierSetAssembler_x86.cpp @@ -103,7 +103,7 @@ void BarrierSetAssembler::load_at(MacroAssembler* masm, DecoratorSet decorators, } void BarrierSetAssembler::store_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type, - Address dst, Register val, Register tmp1, Register tmp2) { + Address dst, Register val, Register tmp1, Register tmp2, Register tmp3) { bool in_heap = (decorators & IN_HEAP) != 0; bool in_native = (decorators & IN_NATIVE) != 0; bool is_not_null = (decorators & IS_NOT_NULL) != 0; diff --git a/src/hotspot/cpu/x86/gc/shared/barrierSetAssembler_x86.hpp b/src/hotspot/cpu/x86/gc/shared/barrierSetAssembler_x86.hpp index 3c63c00e4dbcb8b4fe1fa1c5e34b84684d9691e7..085238d60b55f2caa4dde806b5409cd5864d8a35 100644 --- a/src/hotspot/cpu/x86/gc/shared/barrierSetAssembler_x86.hpp +++ b/src/hotspot/cpu/x86/gc/shared/barrierSetAssembler_x86.hpp @@ -47,7 +47,7 @@ public: virtual void load_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type, Register dst, Address src, Register tmp1, Register tmp_thread); virtual void store_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type, - Address dst, Register val, Register tmp1, Register tmp2); + Address dst, Register val, Register tmp1, Register tmp2, Register tmp3); // Support for jniFastGetField to try resolving a jobject/jweak in native virtual void try_resolve_jobject_in_native(MacroAssembler* masm, Register jni_env, diff --git a/src/hotspot/cpu/x86/gc/shared/cardTableBarrierSetAssembler_x86.cpp b/src/hotspot/cpu/x86/gc/shared/cardTableBarrierSetAssembler_x86.cpp index 7fc36ffae8f0ba32a025bbf2cf81aa71eb85c378..f314cac5980b7f3c9e44ad888383a1139ab1c58d 100644 --- a/src/hotspot/cpu/x86/gc/shared/cardTableBarrierSetAssembler_x86.cpp +++ b/src/hotspot/cpu/x86/gc/shared/cardTableBarrierSetAssembler_x86.cpp @@ -128,7 +128,7 @@ void CardTableBarrierSetAssembler::store_check(MacroAssembler* masm, Register ob } void CardTableBarrierSetAssembler::oop_store_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type, - Address dst, Register val, Register tmp1, Register tmp2) { + Address dst, Register val, Register tmp1, Register tmp2, Register tmp3) { bool in_heap = (decorators & IN_HEAP) != 0; bool is_array = (decorators & IS_ARRAY) != 0; @@ -137,7 +137,7 @@ void CardTableBarrierSetAssembler::oop_store_at(MacroAssembler* masm, DecoratorS bool needs_post_barrier = val != noreg && in_heap; - BarrierSetAssembler::store_at(masm, decorators, type, dst, val, noreg, noreg); + BarrierSetAssembler::store_at(masm, decorators, type, dst, val, noreg, noreg, noreg); if (needs_post_barrier) { // flatten object address if needed if (!precise || (dst.index() == noreg && dst.disp() == 0)) { diff --git a/src/hotspot/cpu/x86/gc/shared/cardTableBarrierSetAssembler_x86.hpp b/src/hotspot/cpu/x86/gc/shared/cardTableBarrierSetAssembler_x86.hpp index a65286bd5996734f49e47f0f2137f27676d3c2f6..4760b222977a81b9e8febd93701786409860835d 100644 --- a/src/hotspot/cpu/x86/gc/shared/cardTableBarrierSetAssembler_x86.hpp +++ b/src/hotspot/cpu/x86/gc/shared/cardTableBarrierSetAssembler_x86.hpp @@ -35,7 +35,7 @@ protected: virtual void gen_write_ref_array_post_barrier(MacroAssembler* masm, DecoratorSet decorators, Register addr, Register count, Register tmp); virtual void oop_store_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type, - Address dst, Register val, Register tmp1, Register tmp2); + Address dst, Register val, Register tmp1, Register tmp2, Register tmp3); }; #endif // CPU_X86_GC_SHARED_CARDTABLEBARRIERSETASSEMBLER_X86_HPP diff --git a/src/hotspot/cpu/x86/gc/shared/modRefBarrierSetAssembler_x86.cpp b/src/hotspot/cpu/x86/gc/shared/modRefBarrierSetAssembler_x86.cpp index 9325ab7ecf9c711605f1fe75d637782d2fecdcca..618095bdfa634b8c3a7cdccab5e280ae96668c1b 100644 --- a/src/hotspot/cpu/x86/gc/shared/modRefBarrierSetAssembler_x86.cpp +++ b/src/hotspot/cpu/x86/gc/shared/modRefBarrierSetAssembler_x86.cpp @@ -84,10 +84,10 @@ void ModRefBarrierSetAssembler::arraycopy_epilogue(MacroAssembler* masm, Decorat } void ModRefBarrierSetAssembler::store_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type, - Address dst, Register val, Register tmp1, Register tmp2) { + Address dst, Register val, Register tmp1, Register tmp2, Register tmp3) { if (is_reference_type(type)) { - oop_store_at(masm, decorators, type, dst, val, tmp1, tmp2); + oop_store_at(masm, decorators, type, dst, val, tmp1, tmp2, tmp3); } else { - BarrierSetAssembler::store_at(masm, decorators, type, dst, val, tmp1, tmp2); + BarrierSetAssembler::store_at(masm, decorators, type, dst, val, tmp1, tmp2, tmp3); } } diff --git a/src/hotspot/cpu/x86/gc/shared/modRefBarrierSetAssembler_x86.hpp b/src/hotspot/cpu/x86/gc/shared/modRefBarrierSetAssembler_x86.hpp index 39950225bfe736a71f7b6dc34a021e78357b110e..c8b5043256ad203bed7d16f7ead5e188c91cbb45 100644 --- a/src/hotspot/cpu/x86/gc/shared/modRefBarrierSetAssembler_x86.hpp +++ b/src/hotspot/cpu/x86/gc/shared/modRefBarrierSetAssembler_x86.hpp @@ -39,7 +39,7 @@ protected: virtual void gen_write_ref_array_post_barrier(MacroAssembler* masm, DecoratorSet decorators, Register addr, Register count, Register tmp) {} virtual void oop_store_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type, - Address dst, Register val, Register tmp1, Register tmp2) = 0; + Address dst, Register val, Register tmp1, Register tmp2, Register tmp3) = 0; public: virtual void arraycopy_prologue(MacroAssembler* masm, DecoratorSet decorators, BasicType type, Register src, Register dst, Register count); @@ -47,7 +47,7 @@ public: Register src, Register dst, Register count); virtual void store_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type, - Address dst, Register val, Register tmp1, Register tmp2); + Address dst, Register val, Register tmp1, Register tmp2, Register tmp3); }; #endif // CPU_X86_GC_SHARED_MODREFBARRIERSETASSEMBLER_X86_HPP diff --git a/src/hotspot/cpu/x86/gc/shenandoah/shenandoahBarrierSetAssembler_x86.cpp b/src/hotspot/cpu/x86/gc/shenandoah/shenandoahBarrierSetAssembler_x86.cpp index 64169b015293084fc4a9ec692c5d88977d38af6a..d213e6fda394e6796bddf81a2a22aef405026b66 100644 --- a/src/hotspot/cpu/x86/gc/shenandoah/shenandoahBarrierSetAssembler_x86.cpp +++ b/src/hotspot/cpu/x86/gc/shenandoah/shenandoahBarrierSetAssembler_x86.cpp @@ -591,7 +591,7 @@ void ShenandoahBarrierSetAssembler::load_at(MacroAssembler* masm, DecoratorSet d } void ShenandoahBarrierSetAssembler::store_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type, - Address dst, Register val, Register tmp1, Register tmp2) { + Address dst, Register val, Register tmp1, Register tmp2, Register tmp3) { bool on_oop = is_reference_type(type); bool in_heap = (decorators & IN_HEAP) != 0; @@ -599,7 +599,6 @@ void ShenandoahBarrierSetAssembler::store_at(MacroAssembler* masm, DecoratorSet if (on_oop && in_heap) { bool needs_pre_barrier = as_normal; - Register tmp3 = LP64_ONLY(r8) NOT_LP64(rsi); Register rthread = LP64_ONLY(r15_thread) NOT_LP64(rcx); // flatten object address if needed // We do it regardless of precise because we need the registers @@ -629,14 +628,14 @@ void ShenandoahBarrierSetAssembler::store_at(MacroAssembler* masm, DecoratorSet false /* expand_call */); } if (val == noreg) { - BarrierSetAssembler::store_at(masm, decorators, type, Address(tmp1, 0), val, noreg, noreg); + BarrierSetAssembler::store_at(masm, decorators, type, Address(tmp1, 0), val, noreg, noreg, noreg); } else { iu_barrier(masm, val, tmp3); - BarrierSetAssembler::store_at(masm, decorators, type, Address(tmp1, 0), val, noreg, noreg); + BarrierSetAssembler::store_at(masm, decorators, type, Address(tmp1, 0), val, noreg, noreg, noreg); } NOT_LP64(imasm->restore_bcp()); } else { - BarrierSetAssembler::store_at(masm, decorators, type, dst, val, tmp1, tmp2); + BarrierSetAssembler::store_at(masm, decorators, type, dst, val, tmp1, tmp2, tmp3); } } diff --git a/src/hotspot/cpu/x86/gc/shenandoah/shenandoahBarrierSetAssembler_x86.hpp b/src/hotspot/cpu/x86/gc/shenandoah/shenandoahBarrierSetAssembler_x86.hpp index 2a8c0862b9e6380c85c18570693e8e3d483fc655..47dfe1449280259f524318b1adf4fc4b573787c8 100644 --- a/src/hotspot/cpu/x86/gc/shenandoah/shenandoahBarrierSetAssembler_x86.hpp +++ b/src/hotspot/cpu/x86/gc/shenandoah/shenandoahBarrierSetAssembler_x86.hpp @@ -77,7 +77,7 @@ public: virtual void load_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type, Register dst, Address src, Register tmp1, Register tmp_thread); virtual void store_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type, - Address dst, Register val, Register tmp1, Register tmp2); + Address dst, Register val, Register tmp1, Register tmp2, Register tmp3); virtual void try_resolve_jobject_in_native(MacroAssembler* masm, Register jni_env, Register obj, Register tmp, Label& slowpath); }; diff --git a/src/hotspot/cpu/x86/gc/z/zBarrierSetAssembler_x86.cpp b/src/hotspot/cpu/x86/gc/z/zBarrierSetAssembler_x86.cpp index 3ffd3a2a85f4062164a413b982774574c81a46e5..00071d66da34166365cd8e10f56d832988295377 100644 --- a/src/hotspot/cpu/x86/gc/z/zBarrierSetAssembler_x86.cpp +++ b/src/hotspot/cpu/x86/gc/z/zBarrierSetAssembler_x86.cpp @@ -193,7 +193,8 @@ void ZBarrierSetAssembler::store_at(MacroAssembler* masm, Address dst, Register src, Register tmp1, - Register tmp2) { + Register tmp2, + Register tmp3) { BLOCK_COMMENT("ZBarrierSetAssembler::store_at {"); // Verify oop store @@ -211,7 +212,7 @@ void ZBarrierSetAssembler::store_at(MacroAssembler* masm, } // Store value - BarrierSetAssembler::store_at(masm, decorators, type, dst, src, tmp1, tmp2); + BarrierSetAssembler::store_at(masm, decorators, type, dst, src, tmp1, tmp2, tmp3); BLOCK_COMMENT("} ZBarrierSetAssembler::store_at"); } @@ -452,7 +453,7 @@ private: void opmask_register_save(KRegister reg) { _spill_offset -= 8; - __ kmovql(Address(rsp, _spill_offset), reg); + __ kmov(Address(rsp, _spill_offset), reg); } void gp_register_restore(Register reg) { @@ -461,7 +462,7 @@ private: } void opmask_register_restore(KRegister reg) { - __ kmovql(reg, Address(rsp, _spill_offset)); + __ kmov(reg, Address(rsp, _spill_offset)); _spill_offset += 8; } diff --git a/src/hotspot/cpu/x86/gc/z/zBarrierSetAssembler_x86.hpp b/src/hotspot/cpu/x86/gc/z/zBarrierSetAssembler_x86.hpp index 134f7e6c9e2e5951a63a8a816c3d1ddd311332df..2446bd1e46a73357d47f9fda7a95828d9a13df8a 100644 --- a/src/hotspot/cpu/x86/gc/z/zBarrierSetAssembler_x86.hpp +++ b/src/hotspot/cpu/x86/gc/z/zBarrierSetAssembler_x86.hpp @@ -61,7 +61,8 @@ public: Address dst, Register src, Register tmp1, - Register tmp2); + Register tmp2, + Register tmp3); #endif // ASSERT virtual void arraycopy_prologue(MacroAssembler* masm, diff --git a/src/hotspot/cpu/x86/interp_masm_x86.cpp b/src/hotspot/cpu/x86/interp_masm_x86.cpp index bf8b94a6319dbacfe7a14d0228fb3fb50689a3f8..34d4178b8da4c39e4412428ddb1cb222098532ce 100644 --- a/src/hotspot/cpu/x86/interp_masm_x86.cpp +++ b/src/hotspot/cpu/x86/interp_masm_x86.cpp @@ -1972,19 +1972,18 @@ void InterpreterMacroAssembler::verify_FPU(int stack_depth, TosState state) { #endif } -// Jump if ((*counter_addr += increment) & mask) satisfies the condition. -void InterpreterMacroAssembler::increment_mask_and_jump(Address counter_addr, - int increment, Address mask, - Register scratch, bool preloaded, - Condition cond, Label* where) { - if (!preloaded) { - movl(scratch, counter_addr); - } - incrementl(scratch, increment); +// Jump if ((*counter_addr += increment) & mask) == 0 +void InterpreterMacroAssembler::increment_mask_and_jump(Address counter_addr, Address mask, + Register scratch, Label* where) { + // This update is actually not atomic and can lose a number of updates + // under heavy contention, but the alternative of using the (contended) + // atomic update here penalizes profiling paths too much. + movl(scratch, counter_addr); + incrementl(scratch, InvocationCounter::count_increment); movl(counter_addr, scratch); andl(scratch, mask); if (where != NULL) { - jcc(cond, *where); + jcc(Assembler::zero, *where); } } diff --git a/src/hotspot/cpu/x86/interp_masm_x86.hpp b/src/hotspot/cpu/x86/interp_masm_x86.hpp index 0aecb6b4a25e6bf47d3876060c7940e7bb276003..a94f35426b8bcaa186f7e3b54c8c8314fc4e59d5 100644 --- a/src/hotspot/cpu/x86/interp_masm_x86.hpp +++ b/src/hotspot/cpu/x86/interp_masm_x86.hpp @@ -248,10 +248,8 @@ class InterpreterMacroAssembler: public MacroAssembler { bool decrement = false); void increment_mdp_data_at(Register mdp_in, Register reg, int constant, bool decrement = false); - void increment_mask_and_jump(Address counter_addr, - int increment, Address mask, - Register scratch, bool preloaded, - Condition cond, Label* where); + void increment_mask_and_jump(Address counter_addr, Address mask, + Register scratch, Label* where); void set_mdp_flag_at(Register mdp_in, int flag_constant); void test_mdp_data_at(Register mdp_in, int offset, Register value, Register test_value_out, diff --git a/src/hotspot/cpu/x86/macroAssembler_x86.cpp b/src/hotspot/cpu/x86/macroAssembler_x86.cpp index 10a1cb4b6a1a0c094566558413e86fbdc0a9beff..e9285b11e42b6facfbb87cb7588691c3e13d7146 100644 --- a/src/hotspot/cpu/x86/macroAssembler_x86.cpp +++ b/src/hotspot/cpu/x86/macroAssembler_x86.cpp @@ -26,6 +26,7 @@ #include "jvm.h" #include "asm/assembler.hpp" #include "asm/assembler.inline.hpp" +#include "c1/c1_FrameMap.hpp" #include "compiler/compiler_globals.hpp" #include "compiler/disassembler.hpp" #include "gc/shared/barrierSet.hpp" @@ -332,21 +333,6 @@ void MacroAssembler::movptr(Address dst, intptr_t src) { movl(dst, src); } - -void MacroAssembler::pop_callee_saved_registers() { - pop(rcx); - pop(rdx); - pop(rdi); - pop(rsi); -} - -void MacroAssembler::push_callee_saved_registers() { - push(rsi); - push(rdi); - push(rdx); - push(rcx); -} - void MacroAssembler::pushoop(jobject obj) { push_literal32((int32_t)obj, oop_Relocation::spec_for_immediate()); } @@ -3593,6 +3579,190 @@ void MacroAssembler::tlab_allocate(Register thread, Register obj, bs->tlab_allocate(this, thread, obj, var_size_in_bytes, con_size_in_bytes, t1, t2, slow_case); } +RegSet MacroAssembler::call_clobbered_gp_registers() { + RegSet regs; +#ifdef _LP64 + regs += RegSet::of(rax, rcx, rdx); +#ifndef WINDOWS + regs += RegSet::of(rsi, rdi); +#endif + regs += RegSet::range(r8, r11); +#else + regs += RegSet::of(rax, rcx, rdx); +#endif + return regs; +} + +XMMRegSet MacroAssembler::call_clobbered_xmm_registers() { +#if defined(WINDOWS) && defined(_LP64) + XMMRegSet result = XMMRegSet::range(xmm0, xmm5); + if (FrameMap::get_num_caller_save_xmms() > 16) { + result += XMMRegSet::range(xmm16, as_XMMRegister(FrameMap::get_num_caller_save_xmms() - 1)); + } + return result; +#else + return XMMRegSet::range(xmm0, as_XMMRegister(FrameMap::get_num_caller_save_xmms() - 1)); +#endif +} + +static int FPUSaveAreaSize = align_up(108, StackAlignmentInBytes); // 108 bytes needed for FPU state by fsave/frstor + +#ifndef _LP64 +static bool use_x87_registers() { return UseSSE < 2; } +#endif +static bool use_xmm_registers() { return UseSSE >= 1; } + +// C1 only ever uses the first double/float of the XMM register. +static int xmm_save_size() { return UseSSE >= 2 ? sizeof(double) : sizeof(float); } + +static void save_xmm_register(MacroAssembler* masm, int offset, XMMRegister reg) { + if (UseSSE == 1) { + masm->movflt(Address(rsp, offset), reg); + } else { + masm->movdbl(Address(rsp, offset), reg); + } +} + +static void restore_xmm_register(MacroAssembler* masm, int offset, XMMRegister reg) { + if (UseSSE == 1) { + masm->movflt(reg, Address(rsp, offset)); + } else { + masm->movdbl(reg, Address(rsp, offset)); + } +} + +int register_section_sizes(RegSet gp_registers, XMMRegSet xmm_registers, bool save_fpu, + int& gp_area_size, int& fp_area_size, int& xmm_area_size) { + + gp_area_size = align_up(gp_registers.size() * RegisterImpl::max_slots_per_register * VMRegImpl::stack_slot_size, + StackAlignmentInBytes); +#ifdef _LP64 + fp_area_size = 0; +#else + fp_area_size = (save_fpu && use_x87_registers()) ? FPUSaveAreaSize : 0; +#endif + xmm_area_size = (save_fpu && use_xmm_registers()) ? xmm_registers.size() * xmm_save_size() : 0; + + return gp_area_size + fp_area_size + xmm_area_size; +} + +void MacroAssembler::push_call_clobbered_registers_except(RegSet exclude, bool save_fpu) { + block_comment("push_call_clobbered_registers start"); + // Regular registers + RegSet gp_registers_to_push = call_clobbered_gp_registers() - exclude; + + int gp_area_size; + int fp_area_size; + int xmm_area_size; + int total_save_size = register_section_sizes(gp_registers_to_push, call_clobbered_xmm_registers(), save_fpu, + gp_area_size, fp_area_size, xmm_area_size); + subptr(rsp, total_save_size); + + push_set(gp_registers_to_push, 0); + +#ifndef _LP64 + if (save_fpu && use_x87_registers()) { + fnsave(Address(rsp, gp_area_size)); + fwait(); + } +#endif + if (save_fpu && use_xmm_registers()) { + push_set(call_clobbered_xmm_registers(), gp_area_size + fp_area_size); + } + + block_comment("push_call_clobbered_registers end"); +} + +void MacroAssembler::pop_call_clobbered_registers_except(RegSet exclude, bool restore_fpu) { + block_comment("pop_call_clobbered_registers start"); + + RegSet gp_registers_to_pop = call_clobbered_gp_registers() - exclude; + + int gp_area_size; + int fp_area_size; + int xmm_area_size; + int total_save_size = register_section_sizes(gp_registers_to_pop, call_clobbered_xmm_registers(), restore_fpu, + gp_area_size, fp_area_size, xmm_area_size); + + if (restore_fpu && use_xmm_registers()) { + pop_set(call_clobbered_xmm_registers(), gp_area_size + fp_area_size); + } +#ifndef _LP64 + if (restore_fpu && use_x87_registers()) { + frstor(Address(rsp, gp_area_size)); + } +#endif + + pop_set(gp_registers_to_pop, 0); + + addptr(rsp, total_save_size); + + vzeroupper(); + + block_comment("pop_call_clobbered_registers end"); +} + +void MacroAssembler::push_set(XMMRegSet set, int offset) { + assert(is_aligned(set.size() * xmm_save_size(), StackAlignmentInBytes), "must be"); + int spill_offset = offset; + + for (RegSetIterator it = set.begin(); *it != xnoreg; ++it) { + save_xmm_register(this, spill_offset, *it); + spill_offset += xmm_save_size(); + } +} + +void MacroAssembler::pop_set(XMMRegSet set, int offset) { + int restore_size = set.size() * xmm_save_size(); + assert(is_aligned(restore_size, StackAlignmentInBytes), "must be"); + + int restore_offset = offset + restore_size - xmm_save_size(); + + for (ReverseRegSetIterator it = set.rbegin(); *it != xnoreg; ++it) { + restore_xmm_register(this, restore_offset, *it); + restore_offset -= xmm_save_size(); + } +} + +void MacroAssembler::push_set(RegSet set, int offset) { + int spill_offset; + if (offset == -1) { + int register_push_size = set.size() * RegisterImpl::max_slots_per_register * VMRegImpl::stack_slot_size; + int aligned_size = align_up(register_push_size, StackAlignmentInBytes); + subptr(rsp, aligned_size); + spill_offset = 0; + } else { + spill_offset = offset; + } + + for (RegSetIterator it = set.begin(); *it != noreg; ++it) { + movptr(Address(rsp, spill_offset), *it); + spill_offset += RegisterImpl::max_slots_per_register * VMRegImpl::stack_slot_size; + } +} + +void MacroAssembler::pop_set(RegSet set, int offset) { + + int gp_reg_size = RegisterImpl::max_slots_per_register * VMRegImpl::stack_slot_size; + int restore_size = set.size() * gp_reg_size; + int aligned_size = align_up(restore_size, StackAlignmentInBytes); + + int restore_offset; + if (offset == -1) { + restore_offset = restore_size - gp_reg_size; + } else { + restore_offset = offset + restore_size - gp_reg_size; + } + for (ReverseRegSetIterator it = set.rbegin(); *it != noreg; ++it) { + movptr(*it, Address(rsp, restore_offset)); + restore_offset -= gp_reg_size; + } + + if (offset == -1) { + addptr(rsp, aligned_size); + } +} + // Defines obj, preserves var_size_in_bytes void MacroAssembler::eden_allocate(Register thread, Register obj, Register var_size_in_bytes, @@ -4605,14 +4775,14 @@ void MacroAssembler::access_load_at(BasicType type, DecoratorSet decorators, Reg } void MacroAssembler::access_store_at(BasicType type, DecoratorSet decorators, Address dst, Register src, - Register tmp1, Register tmp2) { + Register tmp1, Register tmp2, Register tmp3) { BarrierSetAssembler* bs = BarrierSet::barrier_set()->barrier_set_assembler(); decorators = AccessInternal::decorator_fixup(decorators); bool as_raw = (decorators & AS_RAW) != 0; if (as_raw) { - bs->BarrierSetAssembler::store_at(this, decorators, type, dst, src, tmp1, tmp2); + bs->BarrierSetAssembler::store_at(this, decorators, type, dst, src, tmp1, tmp2, tmp3); } else { - bs->store_at(this, decorators, type, dst, src, tmp1, tmp2); + bs->store_at(this, decorators, type, dst, src, tmp1, tmp2, tmp3); } } @@ -4628,13 +4798,13 @@ void MacroAssembler::load_heap_oop_not_null(Register dst, Address src, Register } void MacroAssembler::store_heap_oop(Address dst, Register src, Register tmp1, - Register tmp2, DecoratorSet decorators) { - access_store_at(T_OBJECT, IN_HEAP | decorators, dst, src, tmp1, tmp2); + Register tmp2, Register tmp3, DecoratorSet decorators) { + access_store_at(T_OBJECT, IN_HEAP | decorators, dst, src, tmp1, tmp2, tmp3); } // Used for storing NULLs. void MacroAssembler::store_heap_oop_null(Address dst) { - access_store_at(T_OBJECT, IN_HEAP, dst, noreg, noreg, noreg); + access_store_at(T_OBJECT, IN_HEAP, dst, noreg, noreg, noreg, noreg); } #ifdef _LP64 diff --git a/src/hotspot/cpu/x86/macroAssembler_x86.hpp b/src/hotspot/cpu/x86/macroAssembler_x86.hpp index 3593874866ca81157b1fa49f975034d866383443..9b3da9d5de15cce9a36f1ac9438c47f715701f44 100644 --- a/src/hotspot/cpu/x86/macroAssembler_x86.hpp +++ b/src/hotspot/cpu/x86/macroAssembler_x86.hpp @@ -26,6 +26,7 @@ #define CPU_X86_MACROASSEMBLER_X86_HPP #include "asm/assembler.hpp" +#include "asm/register.hpp" #include "code/vmreg.inline.hpp" #include "compiler/oopMap.hpp" #include "utilities/macros.hpp" @@ -345,14 +346,14 @@ class MacroAssembler: public Assembler { void access_load_at(BasicType type, DecoratorSet decorators, Register dst, Address src, Register tmp1, Register thread_tmp); void access_store_at(BasicType type, DecoratorSet decorators, Address dst, Register src, - Register tmp1, Register tmp2); + Register tmp1, Register tmp2, Register tmp3); void load_heap_oop(Register dst, Address src, Register tmp1 = noreg, Register thread_tmp = noreg, DecoratorSet decorators = 0); void load_heap_oop_not_null(Register dst, Address src, Register tmp1 = noreg, Register thread_tmp = noreg, DecoratorSet decorators = 0); void store_heap_oop(Address dst, Register src, Register tmp1 = noreg, - Register tmp2 = noreg, DecoratorSet decorators = 0); + Register tmp2 = noreg, Register tmp3 = noreg, DecoratorSet decorators = 0); // Used for storing NULL. All other oop constants should be // stored using routines that take a jobject. @@ -521,9 +522,34 @@ class MacroAssembler: public Assembler { // Round up to a power of two void round_to(Register reg, int modulus); - // Callee saved registers handling - void push_callee_saved_registers(); - void pop_callee_saved_registers(); +private: + // General purpose and XMM registers potentially clobbered by native code; there + // is no need for FPU or AVX opmask related methods because C1/interpreter + // - we save/restore FPU state as a whole always + // - do not care about AVX-512 opmask + static RegSet call_clobbered_gp_registers(); + static XMMRegSet call_clobbered_xmm_registers(); + + void push_set(XMMRegSet set, int offset); + void pop_set(XMMRegSet set, int offset); + +public: + void push_set(RegSet set, int offset = -1); + void pop_set(RegSet set, int offset = -1); + + // Push and pop everything that might be clobbered by a native + // runtime call. + // Only save the lower 64 bits of each vector register. + // Additonal registers can be excluded in a passed RegSet. + void push_call_clobbered_registers_except(RegSet exclude, bool save_fpu = true); + void pop_call_clobbered_registers_except(RegSet exclude, bool restore_fpu = true); + + void push_call_clobbered_registers(bool save_fpu = true) { + push_call_clobbered_registers_except(RegSet(), save_fpu); + } + void pop_call_clobbered_registers(bool restore_fpu = true) { + pop_call_clobbered_registers_except(RegSet(), restore_fpu); + } // allocation void eden_allocate( diff --git a/src/hotspot/cpu/x86/matcher_x86.hpp b/src/hotspot/cpu/x86/matcher_x86.hpp index 61af24cf31c52261cbb2fd7149c880f1a22373fb..9711bc8c2c4368d36d616aacb13c54511ac67fe7 100644 --- a/src/hotspot/cpu/x86/matcher_x86.hpp +++ b/src/hotspot/cpu/x86/matcher_x86.hpp @@ -183,4 +183,13 @@ // Implements a variant of EncodeISOArrayNode that encode ASCII only static const bool supports_encode_ascii_array = true; + // Returns pre-selection estimated cost of a vector operation. + static int vector_op_pre_select_sz_estimate(int vopc, BasicType ety, int vlen) { + switch(vopc) { + default: return 0; + case Op_PopCountVI: return VM_Version::supports_avx512_vpopcntdq() ? 0 : 50; + case Op_PopCountVL: return VM_Version::supports_avx512_vpopcntdq() ? 0 : 40; + } + } + #endif // CPU_X86_MATCHER_X86_HPP diff --git a/src/hotspot/cpu/x86/register_definitions_x86.cpp b/src/hotspot/cpu/x86/register_definitions_x86.cpp deleted file mode 100644 index 07466930ffac0df7d3b0e60474e26948613c71e7..0000000000000000000000000000000000000000 --- a/src/hotspot/cpu/x86/register_definitions_x86.cpp +++ /dev/null @@ -1,143 +0,0 @@ -/* - * Copyright (c) 2002, 2016, Oracle and/or its affiliates. All rights reserved. - * 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 "precompiled.hpp" -#include "asm/assembler.hpp" -#include "asm/register.hpp" -#include "register_x86.hpp" -#include "interp_masm_x86.hpp" - -REGISTER_DEFINITION(Register, noreg); -REGISTER_DEFINITION(Register, rax); -REGISTER_DEFINITION(Register, rcx); -REGISTER_DEFINITION(Register, rdx); -REGISTER_DEFINITION(Register, rbx); -REGISTER_DEFINITION(Register, rsp); -REGISTER_DEFINITION(Register, rbp); -REGISTER_DEFINITION(Register, rsi); -REGISTER_DEFINITION(Register, rdi); -#ifdef AMD64 -REGISTER_DEFINITION(Register, r8); -REGISTER_DEFINITION(Register, r9); -REGISTER_DEFINITION(Register, r10); -REGISTER_DEFINITION(Register, r11); -REGISTER_DEFINITION(Register, r12); -REGISTER_DEFINITION(Register, r13); -REGISTER_DEFINITION(Register, r14); -REGISTER_DEFINITION(Register, r15); -#endif // AMD64 - -REGISTER_DEFINITION(FloatRegister, fnoreg); - -REGISTER_DEFINITION(XMMRegister, xnoreg); -REGISTER_DEFINITION(XMMRegister, xmm0 ); -REGISTER_DEFINITION(XMMRegister, xmm1 ); -REGISTER_DEFINITION(XMMRegister, xmm2 ); -REGISTER_DEFINITION(XMMRegister, xmm3 ); -REGISTER_DEFINITION(XMMRegister, xmm4 ); -REGISTER_DEFINITION(XMMRegister, xmm5 ); -REGISTER_DEFINITION(XMMRegister, xmm6 ); -REGISTER_DEFINITION(XMMRegister, xmm7 ); -#ifdef AMD64 -REGISTER_DEFINITION(XMMRegister, xmm8); -REGISTER_DEFINITION(XMMRegister, xmm9); -REGISTER_DEFINITION(XMMRegister, xmm10); -REGISTER_DEFINITION(XMMRegister, xmm11); -REGISTER_DEFINITION(XMMRegister, xmm12); -REGISTER_DEFINITION(XMMRegister, xmm13); -REGISTER_DEFINITION(XMMRegister, xmm14); -REGISTER_DEFINITION(XMMRegister, xmm15); -REGISTER_DEFINITION(XMMRegister, xmm16); -REGISTER_DEFINITION(XMMRegister, xmm17); -REGISTER_DEFINITION(XMMRegister, xmm18); -REGISTER_DEFINITION(XMMRegister, xmm19); -REGISTER_DEFINITION(XMMRegister, xmm20); -REGISTER_DEFINITION(XMMRegister, xmm21); -REGISTER_DEFINITION(XMMRegister, xmm22); -REGISTER_DEFINITION(XMMRegister, xmm23); -REGISTER_DEFINITION(XMMRegister, xmm24); -REGISTER_DEFINITION(XMMRegister, xmm25); -REGISTER_DEFINITION(XMMRegister, xmm26); -REGISTER_DEFINITION(XMMRegister, xmm27); -REGISTER_DEFINITION(XMMRegister, xmm28); -REGISTER_DEFINITION(XMMRegister, xmm29); -REGISTER_DEFINITION(XMMRegister, xmm30); -REGISTER_DEFINITION(XMMRegister, xmm31); - -REGISTER_DEFINITION(Register, c_rarg0); -REGISTER_DEFINITION(Register, c_rarg1); -REGISTER_DEFINITION(Register, c_rarg2); -REGISTER_DEFINITION(Register, c_rarg3); - -REGISTER_DEFINITION(XMMRegister, c_farg0); -REGISTER_DEFINITION(XMMRegister, c_farg1); -REGISTER_DEFINITION(XMMRegister, c_farg2); -REGISTER_DEFINITION(XMMRegister, c_farg3); - -// Non windows OS's have a few more argument registers -#ifndef _WIN64 -REGISTER_DEFINITION(Register, c_rarg4); -REGISTER_DEFINITION(Register, c_rarg5); - -REGISTER_DEFINITION(XMMRegister, c_farg4); -REGISTER_DEFINITION(XMMRegister, c_farg5); -REGISTER_DEFINITION(XMMRegister, c_farg6); -REGISTER_DEFINITION(XMMRegister, c_farg7); -#endif /* _WIN64 */ - -REGISTER_DEFINITION(Register, j_rarg0); -REGISTER_DEFINITION(Register, j_rarg1); -REGISTER_DEFINITION(Register, j_rarg2); -REGISTER_DEFINITION(Register, j_rarg3); -REGISTER_DEFINITION(Register, j_rarg4); -REGISTER_DEFINITION(Register, j_rarg5); - -REGISTER_DEFINITION(XMMRegister, j_farg0); -REGISTER_DEFINITION(XMMRegister, j_farg1); -REGISTER_DEFINITION(XMMRegister, j_farg2); -REGISTER_DEFINITION(XMMRegister, j_farg3); -REGISTER_DEFINITION(XMMRegister, j_farg4); -REGISTER_DEFINITION(XMMRegister, j_farg5); -REGISTER_DEFINITION(XMMRegister, j_farg6); -REGISTER_DEFINITION(XMMRegister, j_farg7); - -REGISTER_DEFINITION(Register, rscratch1); -REGISTER_DEFINITION(Register, rscratch2); - -REGISTER_DEFINITION(Register, r12_heapbase); -REGISTER_DEFINITION(Register, r15_thread); -#endif // AMD64 - -REGISTER_DEFINITION(KRegister, knoreg); -REGISTER_DEFINITION(KRegister, k0); -REGISTER_DEFINITION(KRegister, k1); -REGISTER_DEFINITION(KRegister, k2); -REGISTER_DEFINITION(KRegister, k3); -REGISTER_DEFINITION(KRegister, k4); -REGISTER_DEFINITION(KRegister, k5); -REGISTER_DEFINITION(KRegister, k6); -REGISTER_DEFINITION(KRegister, k7); - -// JSR 292 -REGISTER_DEFINITION(Register, rbp_mh_SP_save); diff --git a/src/hotspot/cpu/x86/register_x86.hpp b/src/hotspot/cpu/x86/register_x86.hpp index b9ac28902407560b1d03df290b731b4f407ede7c..f57b1db48c838e86ddddacca263f8d2662f244c8 100644 --- a/src/hotspot/cpu/x86/register_x86.hpp +++ b/src/hotspot/cpu/x86/register_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 @@ -26,6 +26,8 @@ #define CPU_X86_REGISTER_X86_HPP #include "asm/register.hpp" +#include "utilities/count_leading_zeros.hpp" +#include "utilities/powerOfTwo.hpp" class VMRegImpl; typedef VMRegImpl* VMReg; @@ -135,7 +137,7 @@ inline XMMRegister as_XMMRegister(int encoding) { } -// The implementation of XMM registers for the IA32 architecture +// The implementation of XMM registers. class XMMRegisterImpl: public AbstractRegisterImpl { public: enum { @@ -201,11 +203,7 @@ CONSTANT_REGISTER_DECLARATION(XMMRegister, xmm30, (30)); CONSTANT_REGISTER_DECLARATION(XMMRegister, xmm31, (31)); #endif // AMD64 -// Only used by the 32bit stubGenerator. These can't be described by vmreg and hence -// can't be described in oopMaps and therefore can't be used by the compilers (at least -// were deopt might wan't to see them). - -// Use XMMRegister as shortcut +// Use KRegister as shortcut class KRegisterImpl; typedef KRegisterImpl* KRegister; @@ -213,7 +211,7 @@ inline KRegister as_KRegister(int encoding) { return (KRegister)(intptr_t)encoding; } -// The implementation of XMM registers for the IA32 architecture +// The implementation of AVX-3 (AVX-512) opmask registers. class KRegisterImpl : public AbstractRegisterImpl { public: enum { @@ -276,4 +274,33 @@ class ConcreteRegisterImpl : public AbstractRegisterImpl { }; +template <> +inline Register AbstractRegSet::first() { + uint32_t first = _bitset & -_bitset; + return first ? as_Register(exact_log2(first)) : noreg; +} + +template <> +inline Register AbstractRegSet::last() { + if (_bitset == 0) { return noreg; } + uint32_t last = 31 - count_leading_zeros(_bitset); + return as_Register(last); +} + +template <> +inline XMMRegister AbstractRegSet::first() { + uint32_t first = _bitset & -_bitset; + return first ? as_XMMRegister(exact_log2(first)) : xnoreg; +} + +template <> +inline XMMRegister AbstractRegSet::last() { + if (_bitset == 0) { return xnoreg; } + uint32_t last = 31 - count_leading_zeros(_bitset); + return as_XMMRegister(last); +} + +typedef AbstractRegSet RegSet; +typedef AbstractRegSet XMMRegSet; + #endif // CPU_X86_REGISTER_X86_HPP diff --git a/src/hotspot/cpu/x86/sharedRuntime_x86_64.cpp b/src/hotspot/cpu/x86/sharedRuntime_x86_64.cpp index 6597c91bb42ff11d09b4c5c741a35bd0b27f8d25..8bfbe3303da9e9a8f1dc0604cdbaaf6329d780c5 100644 --- a/src/hotspot/cpu/x86/sharedRuntime_x86_64.cpp +++ b/src/hotspot/cpu/x86/sharedRuntime_x86_64.cpp @@ -3002,7 +3002,7 @@ RuntimeStub* SharedRuntime::generate_resolve_blob(address destination, const cha // allocate space for the code ResourceMark rm; - CodeBuffer buffer(name, 1000, 512); + CodeBuffer buffer(name, 1200, 512); MacroAssembler* masm = new MacroAssembler(&buffer); int frame_size_in_words; diff --git a/src/hotspot/cpu/x86/stubGenerator_x86_32.cpp b/src/hotspot/cpu/x86/stubGenerator_x86_32.cpp index 1525d10e5b5f3dea743318ca097dd1b3098dd6f5..24cfc237b23591e90d3633e26529c4c1b5051d09 100644 --- a/src/hotspot/cpu/x86/stubGenerator_x86_32.cpp +++ b/src/hotspot/cpu/x86/stubGenerator_x86_32.cpp @@ -588,6 +588,30 @@ class StubGenerator: public StubCodeGenerator { return start; } + address generate_popcount_avx_lut(const char *stub_name) { + __ align64(); + StubCodeMark mark(this, "StubRoutines", stub_name); + address start = __ pc(); + __ emit_data(0x02010100, relocInfo::none, 0); + __ emit_data(0x03020201, relocInfo::none, 0); + __ emit_data(0x03020201, relocInfo::none, 0); + __ emit_data(0x04030302, relocInfo::none, 0); + __ emit_data(0x02010100, relocInfo::none, 0); + __ emit_data(0x03020201, relocInfo::none, 0); + __ emit_data(0x03020201, relocInfo::none, 0); + __ emit_data(0x04030302, relocInfo::none, 0); + __ emit_data(0x02010100, relocInfo::none, 0); + __ emit_data(0x03020201, relocInfo::none, 0); + __ emit_data(0x03020201, relocInfo::none, 0); + __ emit_data(0x04030302, relocInfo::none, 0); + __ emit_data(0x02010100, relocInfo::none, 0); + __ emit_data(0x03020201, relocInfo::none, 0); + __ emit_data(0x03020201, relocInfo::none, 0); + __ emit_data(0x04030302, relocInfo::none, 0); + return start; + } + + address generate_iota_indices(const char *stub_name) { __ align(CodeEntryAlignment); StubCodeMark mark(this, "StubRoutines", stub_name); @@ -4004,6 +4028,11 @@ class StubGenerator: public StubCodeGenerator { StubRoutines::x86::_vector_int_mask_cmp_bits = generate_vector_mask("vector_int_mask_cmp_bits", 0x00000001); StubRoutines::x86::_vector_iota_indices = generate_iota_indices("iota_indices"); + if (UsePopCountInstruction && VM_Version::supports_avx2() && !VM_Version::supports_avx512_vpopcntdq()) { + // lut implementation influenced by counting 1s algorithm from section 5-1 of Hackers' Delight. + StubRoutines::x86::_vector_popcount_lut = generate_popcount_avx_lut("popcount_lut"); + } + // support for verify_oop (must happen after universe_init) StubRoutines::_verify_oop_subroutine_entry = generate_verify_oop(); diff --git a/src/hotspot/cpu/x86/stubGenerator_x86_64.cpp b/src/hotspot/cpu/x86/stubGenerator_x86_64.cpp index 8b7188ca42c88ff68959b723b177f950d8fa87bc..39d5cbe2fb4638c4e5104bc53c86a13848e85b4c 100644 --- a/src/hotspot/cpu/x86/stubGenerator_x86_64.cpp +++ b/src/hotspot/cpu/x86/stubGenerator_x86_64.cpp @@ -795,6 +795,21 @@ class StubGenerator: public StubCodeGenerator { return start; } + address generate_popcount_avx_lut(const char *stub_name) { + __ align64(); + StubCodeMark mark(this, "StubRoutines", stub_name); + address start = __ pc(); + __ emit_data64(0x0302020102010100, relocInfo::none); + __ emit_data64(0x0403030203020201, relocInfo::none); + __ emit_data64(0x0302020102010100, relocInfo::none); + __ emit_data64(0x0403030203020201, relocInfo::none); + __ emit_data64(0x0302020102010100, relocInfo::none); + __ emit_data64(0x0403030203020201, relocInfo::none); + __ emit_data64(0x0302020102010100, relocInfo::none); + __ emit_data64(0x0403030203020201, relocInfo::none); + return start; + } + address generate_iota_indices(const char *stub_name) { __ align(CodeEntryAlignment); StubCodeMark mark(this, "StubRoutines", stub_name); @@ -2833,7 +2848,7 @@ class StubGenerator: public StubCodeGenerator { __ align(OptoLoopAlignment); __ BIND(L_store_element); - __ store_heap_oop(to_element_addr, rax_oop, noreg, noreg, AS_RAW); // store the oop + __ store_heap_oop(to_element_addr, rax_oop, noreg, noreg, noreg, AS_RAW); // store the oop __ increment(count); // increment the count toward zero __ jcc(Assembler::zero, L_do_card_marks); @@ -7713,6 +7728,11 @@ address generate_avx_ghash_processBlocks() { StubRoutines::x86::_vector_long_sign_mask = generate_vector_mask("vector_long_sign_mask", 0x8000000000000000); StubRoutines::x86::_vector_iota_indices = generate_iota_indices("iota_indices"); + if (UsePopCountInstruction && VM_Version::supports_avx2() && !VM_Version::supports_avx512_vpopcntdq()) { + // lut implementation influenced by counting 1s algorithm from section 5-1 of Hackers' Delight. + StubRoutines::x86::_vector_popcount_lut = generate_popcount_avx_lut("popcount_lut"); + } + // support for verify_oop (must happen after universe_init) if (VerifyOops) { StubRoutines::_verify_oop_subroutine_entry = generate_verify_oop(); diff --git a/src/hotspot/cpu/x86/stubRoutines_x86.cpp b/src/hotspot/cpu/x86/stubRoutines_x86.cpp index 81362c76bd69472828ffcac5040d3d8a5dd1fcd8..f5a0eb623d0d269c89bd905fee044ff47435a5e1 100644 --- a/src/hotspot/cpu/x86/stubRoutines_x86.cpp +++ b/src/hotspot/cpu/x86/stubRoutines_x86.cpp @@ -59,6 +59,7 @@ address StubRoutines::x86::_vector_double_sign_flip = NULL; address StubRoutines::x86::_vector_byte_perm_mask = NULL; address StubRoutines::x86::_vector_long_sign_mask = NULL; address StubRoutines::x86::_vector_iota_indices = NULL; +address StubRoutines::x86::_vector_popcount_lut = NULL; address StubRoutines::x86::_vector_32_bit_mask = NULL; address StubRoutines::x86::_vector_64_bit_mask = NULL; #ifdef _LP64 diff --git a/src/hotspot/cpu/x86/stubRoutines_x86.hpp b/src/hotspot/cpu/x86/stubRoutines_x86.hpp index e4dd9550ce28343e24917176eababb5913835137..5119dde4fd5427a866036ba95425c4116805ce15 100644 --- a/src/hotspot/cpu/x86/stubRoutines_x86.hpp +++ b/src/hotspot/cpu/x86/stubRoutines_x86.hpp @@ -177,6 +177,7 @@ class x86 { static address _vector_short_shuffle_mask; static address _vector_long_shuffle_mask; static address _vector_iota_indices; + static address _vector_popcount_lut; #ifdef _LP64 static juint _k256_W[]; static address _k256_W_adr; @@ -340,6 +341,9 @@ class x86 { return _vector_iota_indices; } + static address vector_popcount_lut() { + return _vector_popcount_lut; + } #ifdef _LP64 static address k256_W_addr() { return _k256_W_adr; } static address k512_W_addr() { return _k512_W_addr; } diff --git a/src/hotspot/cpu/x86/templateInterpreterGenerator_x86.cpp b/src/hotspot/cpu/x86/templateInterpreterGenerator_x86.cpp index ca7bcd8e50ec49d707f55f56589f83f37d6a046c..7b14aff6f1f6e2f7c71b8cd18e9576262a47e20c 100644 --- a/src/hotspot/cpu/x86/templateInterpreterGenerator_x86.cpp +++ b/src/hotspot/cpu/x86/templateInterpreterGenerator_x86.cpp @@ -388,7 +388,6 @@ address TemplateInterpreterGenerator::generate_safept_entry_for( void TemplateInterpreterGenerator::generate_counter_incr(Label* overflow) { Label done; // Note: In tiered we increment either counters in Method* or in MDO depending if we're profiling or not. - int increment = InvocationCounter::count_increment; Label no_mdo; if (ProfileInterpreter) { // Are we profiling? @@ -399,7 +398,7 @@ void TemplateInterpreterGenerator::generate_counter_incr(Label* overflow) { const Address mdo_invocation_counter(rax, in_bytes(MethodData::invocation_counter_offset()) + in_bytes(InvocationCounter::counter_offset())); const Address mask(rax, in_bytes(MethodData::invoke_mask_offset())); - __ increment_mask_and_jump(mdo_invocation_counter, increment, mask, rcx, false, Assembler::zero, overflow); + __ increment_mask_and_jump(mdo_invocation_counter, mask, rcx, overflow); __ jmp(done); } __ bind(no_mdo); @@ -409,8 +408,7 @@ void TemplateInterpreterGenerator::generate_counter_incr(Label* overflow) { InvocationCounter::counter_offset()); __ get_method_counters(rbx, rax, done); const Address mask(rax, in_bytes(MethodCounters::invoke_mask_offset())); - __ increment_mask_and_jump(invocation_counter, increment, mask, rcx, - false, Assembler::zero, overflow); + __ increment_mask_and_jump(invocation_counter, mask, rcx, overflow); __ bind(done); } @@ -755,8 +753,8 @@ void TemplateInterpreterGenerator::bang_stack_shadow_pages(bool native_call) { __ bang_stack_with_offset(p*page_size); } - // Record a new watermark, unless the update is above the safe limit. - // Otherwise, the next time around a check above would pass the safe limit. + // Record the new watermark, but only if update is above the safe limit. + // Otherwise, the next time around the check above would pass the safe limit. __ cmpptr(rsp, Address(thread, JavaThread::shadow_zone_safe_limit())); __ jccb(Assembler::belowEqual, L_done); __ movptr(Address(thread, JavaThread::shadow_zone_growth_watermark()), rsp); diff --git a/src/hotspot/cpu/x86/templateInterpreterGenerator_x86_64.cpp b/src/hotspot/cpu/x86/templateInterpreterGenerator_x86_64.cpp index 8702a28ac689fc071bd4bf91acfcdb7d7bf7adb5..1a1dad0cea317543dda0b0604f8e614097c2233f 100644 --- a/src/hotspot/cpu/x86/templateInterpreterGenerator_x86_64.cpp +++ b/src/hotspot/cpu/x86/templateInterpreterGenerator_x86_64.cpp @@ -69,7 +69,7 @@ address TemplateInterpreterGenerator::generate_slow_signature_handler() { Label isfloatordouble, isdouble, next; __ testl(c_rarg3, 1 << (i*2)); // Float or Double? - __ jcc(Assembler::notZero, isfloatordouble); + __ jccb(Assembler::notZero, isfloatordouble); // Do Int register here switch ( i ) { @@ -88,15 +88,15 @@ address TemplateInterpreterGenerator::generate_slow_signature_handler() { break; } - __ jmp (next); + __ jmpb(next); __ bind(isfloatordouble); __ testl(c_rarg3, 1 << ((i*2)+1)); // Double? - __ jcc(Assembler::notZero, isdouble); + __ jccb(Assembler::notZero, isdouble); // Do Float Here __ movflt(floatreg, Address(rsp, i * wordSize)); - __ jmp(next); + __ jmpb(next); // Do Double here __ bind(isdouble); @@ -150,9 +150,9 @@ address TemplateInterpreterGenerator::generate_slow_signature_handler() { Label d, done; __ testl(c_rarg3, 1 << i); - __ jcc(Assembler::notZero, d); + __ jccb(Assembler::notZero, d); __ movflt(r, Address(rsp, (6 + i) * wordSize)); - __ jmp(done); + __ jmpb(done); __ bind(d); __ movdbl(r, Address(rsp, (6 + i) * wordSize)); __ bind(done); diff --git a/src/hotspot/cpu/x86/templateTable_x86.cpp b/src/hotspot/cpu/x86/templateTable_x86.cpp index 0532fb17785c0faffd5a32bccec88edc19705e70..531ff7956b4bc86007977c5a8c4148f88dde12ef 100644 --- a/src/hotspot/cpu/x86/templateTable_x86.cpp +++ b/src/hotspot/cpu/x86/templateTable_x86.cpp @@ -152,7 +152,7 @@ static void do_oop_store(InterpreterMacroAssembler* _masm, Register val, DecoratorSet decorators = 0) { assert(val == noreg || val == rax, "parameter is just for looks"); - __ store_heap_oop(dst, val, rdx, rbx, decorators); + __ store_heap_oop(dst, val, rdx, rbx, LP64_ONLY(r8) NOT_LP64(rsi), decorators); } static void do_oop_load(InterpreterMacroAssembler* _masm, @@ -1067,7 +1067,7 @@ void TemplateTable::iastore() { __ access_store_at(T_INT, IN_HEAP | IS_ARRAY, Address(rdx, rbx, Address::times_4, arrayOopDesc::base_offset_in_bytes(T_INT)), - rax, noreg, noreg); + rax, noreg, noreg, noreg); } void TemplateTable::lastore() { @@ -1081,7 +1081,7 @@ void TemplateTable::lastore() { __ access_store_at(T_LONG, IN_HEAP | IS_ARRAY, Address(rcx, rbx, Address::times_8, arrayOopDesc::base_offset_in_bytes(T_LONG)), - noreg /* ltos */, noreg, noreg); + noreg /* ltos */, noreg, noreg, noreg); } @@ -1095,7 +1095,7 @@ void TemplateTable::fastore() { __ access_store_at(T_FLOAT, IN_HEAP | IS_ARRAY, Address(rdx, rbx, Address::times_4, arrayOopDesc::base_offset_in_bytes(T_FLOAT)), - noreg /* ftos */, noreg, noreg); + noreg /* ftos */, noreg, noreg, noreg); } void TemplateTable::dastore() { @@ -1108,7 +1108,7 @@ void TemplateTable::dastore() { __ access_store_at(T_DOUBLE, IN_HEAP | IS_ARRAY, Address(rdx, rbx, Address::times_8, arrayOopDesc::base_offset_in_bytes(T_DOUBLE)), - noreg /* dtos */, noreg, noreg); + noreg /* dtos */, noreg, noreg, noreg); } void TemplateTable::aastore() { @@ -1186,7 +1186,7 @@ void TemplateTable::bastore() { __ access_store_at(T_BYTE, IN_HEAP | IS_ARRAY, Address(rdx, rbx,Address::times_1, arrayOopDesc::base_offset_in_bytes(T_BYTE)), - rax, noreg, noreg); + rax, noreg, noreg, noreg); } void TemplateTable::castore() { @@ -1199,7 +1199,7 @@ void TemplateTable::castore() { __ access_store_at(T_CHAR, IN_HEAP | IS_ARRAY, Address(rdx, rbx, Address::times_2, arrayOopDesc::base_offset_in_bytes(T_CHAR)), - rax, noreg, noreg); + rax, noreg, noreg, noreg); } @@ -2197,7 +2197,6 @@ void TemplateTable::branch(bool is_jsr, bool is_wide) { __ bind(has_counters); Label no_mdo; - int increment = InvocationCounter::count_increment; if (ProfileInterpreter) { // Are we profiling? __ movptr(rbx, Address(rcx, in_bytes(Method::method_data_offset()))); @@ -2207,7 +2206,7 @@ void TemplateTable::branch(bool is_jsr, bool is_wide) { const Address mdo_backedge_counter(rbx, in_bytes(MethodData::backedge_counter_offset()) + in_bytes(InvocationCounter::counter_offset())); const Address mask(rbx, in_bytes(MethodData::backedge_mask_offset())); - __ increment_mask_and_jump(mdo_backedge_counter, increment, mask, rax, false, Assembler::zero, + __ increment_mask_and_jump(mdo_backedge_counter, mask, rax, UseOnStackReplacement ? &backedge_counter_overflow : NULL); __ jmp(dispatch); } @@ -2215,8 +2214,8 @@ void TemplateTable::branch(bool is_jsr, bool is_wide) { // Increment backedge counter in MethodCounters* __ movptr(rcx, Address(rcx, Method::method_counters_offset())); const Address mask(rcx, in_bytes(MethodCounters::backedge_mask_offset())); - __ increment_mask_and_jump(Address(rcx, be_offset), increment, mask, - rax, false, Assembler::zero, UseOnStackReplacement ? &backedge_counter_overflow : NULL); + __ increment_mask_and_jump(Address(rcx, be_offset), mask, rax, + UseOnStackReplacement ? &backedge_counter_overflow : NULL); __ bind(dispatch); } @@ -3102,7 +3101,7 @@ void TemplateTable::putfield_or_static_helper(int byte_no, bool is_static, Rewri { __ pop(btos); if (!is_static) pop_and_check_object(obj); - __ access_store_at(T_BYTE, IN_HEAP, field, rax, noreg, noreg); + __ access_store_at(T_BYTE, IN_HEAP, field, rax, noreg, noreg, noreg); if (!is_static && rc == may_rewrite) { patch_bytecode(Bytecodes::_fast_bputfield, bc, rbx, true, byte_no); } @@ -3117,7 +3116,7 @@ void TemplateTable::putfield_or_static_helper(int byte_no, bool is_static, Rewri { __ pop(ztos); if (!is_static) pop_and_check_object(obj); - __ access_store_at(T_BOOLEAN, IN_HEAP, field, rax, noreg, noreg); + __ access_store_at(T_BOOLEAN, IN_HEAP, field, rax, noreg, noreg, noreg); if (!is_static && rc == may_rewrite) { patch_bytecode(Bytecodes::_fast_zputfield, bc, rbx, true, byte_no); } @@ -3148,7 +3147,7 @@ void TemplateTable::putfield_or_static_helper(int byte_no, bool is_static, Rewri { __ pop(itos); if (!is_static) pop_and_check_object(obj); - __ access_store_at(T_INT, IN_HEAP, field, rax, noreg, noreg); + __ access_store_at(T_INT, IN_HEAP, field, rax, noreg, noreg, noreg); if (!is_static && rc == may_rewrite) { patch_bytecode(Bytecodes::_fast_iputfield, bc, rbx, true, byte_no); } @@ -3163,7 +3162,7 @@ void TemplateTable::putfield_or_static_helper(int byte_no, bool is_static, Rewri { __ pop(ctos); if (!is_static) pop_and_check_object(obj); - __ access_store_at(T_CHAR, IN_HEAP, field, rax, noreg, noreg); + __ access_store_at(T_CHAR, IN_HEAP, field, rax, noreg, noreg, noreg); if (!is_static && rc == may_rewrite) { patch_bytecode(Bytecodes::_fast_cputfield, bc, rbx, true, byte_no); } @@ -3178,7 +3177,7 @@ void TemplateTable::putfield_or_static_helper(int byte_no, bool is_static, Rewri { __ pop(stos); if (!is_static) pop_and_check_object(obj); - __ access_store_at(T_SHORT, IN_HEAP, field, rax, noreg, noreg); + __ access_store_at(T_SHORT, IN_HEAP, field, rax, noreg, noreg, noreg); if (!is_static && rc == may_rewrite) { patch_bytecode(Bytecodes::_fast_sputfield, bc, rbx, true, byte_no); } @@ -3194,7 +3193,7 @@ void TemplateTable::putfield_or_static_helper(int byte_no, bool is_static, Rewri __ pop(ltos); if (!is_static) pop_and_check_object(obj); // MO_RELAXED: generate atomic store for the case of volatile field (important for x86_32) - __ access_store_at(T_LONG, IN_HEAP | MO_RELAXED, field, noreg /* ltos*/, noreg, noreg); + __ access_store_at(T_LONG, IN_HEAP | MO_RELAXED, field, noreg /* ltos*/, noreg, noreg, noreg); #ifdef _LP64 if (!is_static && rc == may_rewrite) { patch_bytecode(Bytecodes::_fast_lputfield, bc, rbx, true, byte_no); @@ -3211,7 +3210,7 @@ void TemplateTable::putfield_or_static_helper(int byte_no, bool is_static, Rewri { __ pop(ftos); if (!is_static) pop_and_check_object(obj); - __ access_store_at(T_FLOAT, IN_HEAP, field, noreg /* ftos */, noreg, noreg); + __ access_store_at(T_FLOAT, IN_HEAP, field, noreg /* ftos */, noreg, noreg, noreg); if (!is_static && rc == may_rewrite) { patch_bytecode(Bytecodes::_fast_fputfield, bc, rbx, true, byte_no); } @@ -3230,7 +3229,7 @@ void TemplateTable::putfield_or_static_helper(int byte_no, bool is_static, Rewri __ pop(dtos); if (!is_static) pop_and_check_object(obj); // MO_RELAXED: for the case of volatile field, in fact it adds no extra work for the underlying implementation - __ access_store_at(T_DOUBLE, IN_HEAP | MO_RELAXED, field, noreg /* dtos */, noreg, noreg); + __ access_store_at(T_DOUBLE, IN_HEAP | MO_RELAXED, field, noreg /* dtos */, noreg, noreg, noreg); if (!is_static && rc == may_rewrite) { patch_bytecode(Bytecodes::_fast_dputfield, bc, rbx, true, byte_no); } @@ -3373,31 +3372,31 @@ void TemplateTable::fast_storefield_helper(Address field, Register rax) { break; case Bytecodes::_fast_lputfield: #ifdef _LP64 - __ access_store_at(T_LONG, IN_HEAP, field, noreg /* ltos */, noreg, noreg); + __ access_store_at(T_LONG, IN_HEAP, field, noreg /* ltos */, noreg, noreg, noreg); #else __ stop("should not be rewritten"); #endif break; case Bytecodes::_fast_iputfield: - __ access_store_at(T_INT, IN_HEAP, field, rax, noreg, noreg); + __ access_store_at(T_INT, IN_HEAP, field, rax, noreg, noreg, noreg); break; case Bytecodes::_fast_zputfield: - __ access_store_at(T_BOOLEAN, IN_HEAP, field, rax, noreg, noreg); + __ access_store_at(T_BOOLEAN, IN_HEAP, field, rax, noreg, noreg, noreg); break; case Bytecodes::_fast_bputfield: - __ access_store_at(T_BYTE, IN_HEAP, field, rax, noreg, noreg); + __ access_store_at(T_BYTE, IN_HEAP, field, rax, noreg, noreg, noreg); break; case Bytecodes::_fast_sputfield: - __ access_store_at(T_SHORT, IN_HEAP, field, rax, noreg, noreg); + __ access_store_at(T_SHORT, IN_HEAP, field, rax, noreg, noreg, noreg); break; case Bytecodes::_fast_cputfield: - __ access_store_at(T_CHAR, IN_HEAP, field, rax, noreg, noreg); + __ access_store_at(T_CHAR, IN_HEAP, field, rax, noreg, noreg, noreg); break; case Bytecodes::_fast_fputfield: - __ access_store_at(T_FLOAT, IN_HEAP, field, noreg /* ftos*/, noreg, noreg); + __ access_store_at(T_FLOAT, IN_HEAP, field, noreg /* ftos*/, noreg, noreg, noreg); break; case Bytecodes::_fast_dputfield: - __ access_store_at(T_DOUBLE, IN_HEAP, field, noreg /* dtos*/, noreg, noreg); + __ access_store_at(T_DOUBLE, IN_HEAP, field, noreg /* dtos*/, noreg, noreg, noreg); break; default: ShouldNotReachHere(); diff --git a/src/hotspot/cpu/x86/vm_version_x86.hpp b/src/hotspot/cpu/x86/vm_version_x86.hpp index 2fd1bbc9617002e6c84cb8f5e76fe090ef1b438c..2f4e31b4708ec8e9c777584dd5e1e5ea65111133 100644 --- a/src/hotspot/cpu/x86/vm_version_x86.hpp +++ b/src/hotspot/cpu/x86/vm_version_x86.hpp @@ -1044,6 +1044,25 @@ public: static bool supports_clflushopt() { return ((_features & CPU_FLUSHOPT) != 0); } static bool supports_clwb() { return ((_features & CPU_CLWB) != 0); } + // Old CPUs perform lea on AGU which causes additional latency transfering the + // value from/to ALU for other operations + static bool supports_fast_2op_lea() { + return (is_intel() && supports_avx()) || // Sandy Bridge and above + (is_amd() && supports_avx()); // Jaguar and Bulldozer and above + } + + // Pre Icelake Intels suffer inefficiency regarding 3-operand lea, which contains + // all of base register, index register and displacement immediate, with 3 latency. + // Note that when the address contains no displacement but the base register is + // rbp or r13, the machine code must contain a zero displacement immediate, + // effectively transform a 2-operand lea into a 3-operand lea. This can be + // replaced by add-add or lea-add + static bool supports_fast_3op_lea() { + return supports_fast_2op_lea() && + ((is_intel() && supports_clwb() && !is_intel_skylake()) || // Icelake and above + is_amd()); + } + #ifdef __APPLE__ // Is the CPU running emulated (for example macOS Rosetta running x86_64 code on M1 ARM (aarch64) static bool is_cpu_emulated(); diff --git a/src/hotspot/cpu/x86/x86.ad b/src/hotspot/cpu/x86/x86.ad index 7ff67e9a085562722946e6c04f95cb18e4136fb6..ab28ebd5ca5e1da187a41fd625a5a5350aefea5b 100644 --- a/src/hotspot/cpu/x86/x86.ad +++ b/src/hotspot/cpu/x86/x86.ad @@ -1405,8 +1405,12 @@ const bool Matcher::match_rule_supported(int opcode) { } break; case Op_PopCountVI: + if (!UsePopCountInstruction || (UseAVX < 2)) { + return false; + } + break; case Op_PopCountVL: - if (!UsePopCountInstruction || !VM_Version::supports_avx512_vpopcntdq()) { + if (!UsePopCountInstruction || (UseAVX <= 2)) { return false; } break; @@ -1861,6 +1865,18 @@ const bool Matcher::match_rule_supported_vector(int opcode, int vlen, BasicType return false; } break; + case Op_PopCountVI: + if (!VM_Version::supports_avx512_vpopcntdq() && + (vlen == 16) && !VM_Version::supports_avx512bw()) { + return false; + } + break; + case Op_PopCountVL: + if (!VM_Version::supports_avx512_vpopcntdq() && + ((vlen <= 4) || ((vlen == 8) && !VM_Version::supports_avx512bw()))) { + return false; + } + break; } return true; // Per default match rules are supported. } @@ -8571,28 +8587,54 @@ instruct vmuladdaddS2I_reg(vec dst, vec src1, vec src2) %{ // --------------------------------- PopCount -------------------------------------- -instruct vpopcountI(vec dst, vec src) %{ +instruct vpopcountI_popcntd(vec dst, vec src) %{ + predicate(VM_Version::supports_avx512_vpopcntdq()); match(Set dst (PopCountVI src)); - format %{ "vpopcntd $dst,$src\t! vector popcount packedI" %} + format %{ "vector_popcount_int $dst, $src\t! vector popcount packedI" %} ins_encode %{ assert(UsePopCountInstruction, "not enabled"); + int vlen_enc = vector_length_encoding(this); + __ vector_popcount_int($dst$$XMMRegister, $src$$XMMRegister, xnoreg, xnoreg, xnoreg, noreg, vlen_enc); + %} + ins_pipe( pipe_slow ); +%} +instruct vpopcountI(vec dst, vec src, vec xtmp1, vec xtmp2, vec xtmp3, rRegP rtmp, rFlagsReg cc) %{ + predicate(!VM_Version::supports_avx512_vpopcntdq()); + match(Set dst (PopCountVI src)); + effect(TEMP dst, TEMP xtmp1, TEMP xtmp2, TEMP xtmp3, TEMP rtmp, KILL cc); + format %{ "vector_popcount_int $dst, $src\t! using $xtmp1, $xtmp2, $xtmp3, and $rtmp as TEMP" %} + ins_encode %{ + assert(UsePopCountInstruction, "not enabled"); int vlen_enc = vector_length_encoding(this); - __ vpopcntd($dst$$XMMRegister, $src$$XMMRegister, vlen_enc); + __ vector_popcount_int($dst$$XMMRegister, $src$$XMMRegister, $xtmp1$$XMMRegister, $xtmp2$$XMMRegister, + $xtmp3$$XMMRegister, $rtmp$$Register, vlen_enc); %} ins_pipe( pipe_slow ); %} -instruct vpopcountL(vec dst, vec src) %{ +instruct vpopcountL_popcntd(vec dst, vec src) %{ + predicate(VM_Version::supports_avx512_vpopcntdq()); match(Set dst (PopCountVL src)); - format %{ "vpopcntq $dst,$src\t! vector popcount packedL" %} + format %{ "vector_popcount_long $dst, $src\t! vector popcount packedL" %} ins_encode %{ assert(UsePopCountInstruction, "not enabled"); - int vlen_enc = vector_length_encoding(this, $src); - __ vpopcntq($dst$$XMMRegister, $src$$XMMRegister, vlen_enc); - __ evpmovqd($dst$$XMMRegister, $dst$$XMMRegister, vlen_enc); + __ vector_popcount_long($dst$$XMMRegister, $src$$XMMRegister, xnoreg, xnoreg, xnoreg, noreg, vlen_enc); + %} + ins_pipe( pipe_slow ); +%} +instruct vpopcountL(vec dst, vec src, vec xtmp1, vec xtmp2, vec xtmp3, rRegP rtmp, rFlagsReg cc) %{ + predicate(!VM_Version::supports_avx512_vpopcntdq()); + match(Set dst (PopCountVL src)); + effect(TEMP dst, TEMP xtmp1, TEMP xtmp2, TEMP xtmp3, TEMP rtmp, KILL cc); + format %{ "vector_popcount_long $dst, $src\t! using $xtmp1, $xtmp2, $xtmp3, and $rtmp as TEMP" %} + ins_encode %{ + assert(UsePopCountInstruction, "not enabled"); + int vlen_enc = vector_length_encoding(this, $src); + __ vector_popcount_long($dst$$XMMRegister, $src$$XMMRegister, $xtmp1$$XMMRegister, $xtmp2$$XMMRegister, + $xtmp3$$XMMRegister, $rtmp$$Register, 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 a31a38a384fe54e6b2964dafcea7729eea487928..9bba150516ed134ae16e34b52cf97242f2ef22e7 100644 --- a/src/hotspot/cpu/x86/x86_32.ad +++ b/src/hotspot/cpu/x86/x86_32.ad @@ -1,5 +1,5 @@ // -// Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved. +// Copyright (c) 1997, 2022, Oracle and/or its affiliates. All rights reserved. // DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. // // This code is free software; you can redistribute it and/or modify it @@ -7825,9 +7825,9 @@ instruct divI_eReg(eAXRegI rax, eDXRegI rdx, eCXRegI div, eFlagsReg cr) %{ %} // Divide Register Long -instruct divL_eReg( eADXRegL dst, eRegL src1, eRegL src2, eFlagsReg cr, eCXRegI cx, eBXRegI bx ) %{ +instruct divL_eReg(eADXRegL dst, eRegL src1, eRegL src2) %{ match(Set dst (DivL src1 src2)); - effect( KILL cr, KILL cx, KILL bx ); + effect(CALL); ins_cost(10000); format %{ "PUSH $src1.hi\n\t" "PUSH $src1.lo\n\t" @@ -7873,9 +7873,9 @@ instruct modI_eReg(eDXRegI rdx, eAXRegI rax, eCXRegI div, eFlagsReg cr) %{ %} // Remainder Register Long -instruct modL_eReg( eADXRegL dst, eRegL src1, eRegL src2, eFlagsReg cr, eCXRegI cx, eBXRegI bx ) %{ +instruct modL_eReg(eADXRegL dst, eRegL src1, eRegL src2) %{ match(Set dst (ModL src1 src2)); - effect( KILL cr, KILL cx, KILL bx ); + effect(CALL); ins_cost(10000); format %{ "PUSH $src1.hi\n\t" "PUSH $src1.lo\n\t" @@ -12122,34 +12122,34 @@ instruct array_equalsC_evex(eDIRegP ary1, eSIRegP ary2, eAXRegI result, ins_pipe( pipe_slow ); %} -instruct has_negatives(eSIRegP ary1, eCXRegI len, eAXRegI result, - regD tmp1, regD tmp2, eBXRegI tmp3, eFlagsReg cr) +instruct count_positives(eSIRegP ary1, eCXRegI len, eAXRegI result, + regD tmp1, regD tmp2, eBXRegI tmp3, eFlagsReg cr) %{ predicate(!VM_Version::supports_avx512vlbw() || !VM_Version::supports_bmi2()); - match(Set result (HasNegatives ary1 len)); + match(Set result (CountPositives ary1 len)); effect(TEMP tmp1, TEMP tmp2, USE_KILL ary1, USE_KILL len, KILL tmp3, KILL cr); - format %{ "has negatives byte[] $ary1,$len -> $result // KILL $tmp1, $tmp2, $tmp3" %} + format %{ "countPositives byte[] $ary1,$len -> $result // KILL $tmp1, $tmp2, $tmp3" %} ins_encode %{ - __ has_negatives($ary1$$Register, $len$$Register, - $result$$Register, $tmp3$$Register, - $tmp1$$XMMRegister, $tmp2$$XMMRegister, knoreg, knoreg); + __ count_positives($ary1$$Register, $len$$Register, + $result$$Register, $tmp3$$Register, + $tmp1$$XMMRegister, $tmp2$$XMMRegister, knoreg, knoreg); %} ins_pipe( pipe_slow ); %} -instruct has_negatives_evex(eSIRegP ary1, eCXRegI len, eAXRegI result, - regD tmp1, regD tmp2, kReg ktmp1, kReg ktmp2, eBXRegI tmp3, eFlagsReg cr) +instruct count_positives_evex(eSIRegP ary1, eCXRegI len, eAXRegI result, + regD tmp1, regD tmp2, kReg ktmp1, kReg ktmp2, eBXRegI tmp3, eFlagsReg cr) %{ predicate(VM_Version::supports_avx512vlbw() && VM_Version::supports_bmi2()); - match(Set result (HasNegatives ary1 len)); + match(Set result (CountPositives ary1 len)); effect(TEMP tmp1, TEMP tmp2, TEMP ktmp1, TEMP ktmp2, USE_KILL ary1, USE_KILL len, KILL tmp3, KILL cr); - format %{ "has negatives byte[] $ary1,$len -> $result // KILL $tmp1, $tmp2, $tmp3" %} + format %{ "countPositives byte[] $ary1,$len -> $result // KILL $tmp1, $tmp2, $tmp3" %} ins_encode %{ - __ has_negatives($ary1$$Register, $len$$Register, - $result$$Register, $tmp3$$Register, - $tmp1$$XMMRegister, $tmp2$$XMMRegister, $ktmp1$$KRegister, $ktmp2$$KRegister); + __ count_positives($ary1$$Register, $len$$Register, + $result$$Register, $tmp3$$Register, + $tmp1$$XMMRegister, $tmp2$$XMMRegister, $ktmp1$$KRegister, $ktmp2$$KRegister); %} ins_pipe( pipe_slow ); %} diff --git a/src/hotspot/cpu/x86/x86_64.ad b/src/hotspot/cpu/x86/x86_64.ad index fbf71300dcd6b6da8a0dc4b034f0c152dfdcdaae..09ff707599472eb57dbf77fa9fe21dc12d744b6b 100644 --- a/src/hotspot/cpu/x86/x86_64.ad +++ b/src/hotspot/cpu/x86/x86_64.ad @@ -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 @@ -241,6 +241,11 @@ reg_class long_no_rcx_reg %{ return _LONG_NO_RCX_REG_mask; %} +// Class for all long registers (excluding RBP and R13) +reg_class long_no_rbp_r13_reg %{ + return _LONG_NO_RBP_R13_REG_mask; +%} + // Class for all int registers (excluding RSP) reg_class int_reg %{ return _INT_REG_mask; @@ -256,6 +261,11 @@ reg_class int_no_rcx_reg %{ return _INT_NO_RCX_REG_mask; %} +// Class for all int registers (excluding RBP and R13) +reg_class int_no_rbp_r13_reg %{ + return _INT_NO_RBP_R13_REG_mask; +%} + // Singleton class for RAX pointer register reg_class ptr_rax_reg(RAX, RAX_H); @@ -319,9 +329,11 @@ extern RegMask _PTR_NO_RAX_RBX_REG_mask; extern RegMask _LONG_REG_mask; extern RegMask _LONG_NO_RAX_RDX_REG_mask; extern RegMask _LONG_NO_RCX_REG_mask; +extern RegMask _LONG_NO_RBP_R13_REG_mask; extern RegMask _INT_REG_mask; extern RegMask _INT_NO_RAX_RDX_REG_mask; extern RegMask _INT_NO_RCX_REG_mask; +extern RegMask _INT_NO_RBP_R13_REG_mask; extern RegMask _FLOAT_REG_mask; extern RegMask _STACK_OR_PTR_REG_mask; @@ -348,9 +360,11 @@ RegMask _PTR_NO_RAX_RBX_REG_mask; RegMask _LONG_REG_mask; RegMask _LONG_NO_RAX_RDX_REG_mask; RegMask _LONG_NO_RCX_REG_mask; +RegMask _LONG_NO_RBP_R13_REG_mask; RegMask _INT_REG_mask; RegMask _INT_NO_RAX_RDX_REG_mask; RegMask _INT_NO_RCX_REG_mask; +RegMask _INT_NO_RBP_R13_REG_mask; RegMask _FLOAT_REG_mask; RegMask _STACK_OR_PTR_REG_mask; RegMask _STACK_OR_LONG_REG_mask; @@ -409,6 +423,12 @@ void reg_mask_init() { _LONG_NO_RCX_REG_mask.Remove(OptoReg::as_OptoReg(rcx->as_VMReg())); _LONG_NO_RCX_REG_mask.Remove(OptoReg::as_OptoReg(rcx->as_VMReg()->next())); + _LONG_NO_RBP_R13_REG_mask = _LONG_REG_mask; + _LONG_NO_RBP_R13_REG_mask.Remove(OptoReg::as_OptoReg(rbp->as_VMReg())); + _LONG_NO_RBP_R13_REG_mask.Remove(OptoReg::as_OptoReg(rbp->as_VMReg()->next())); + _LONG_NO_RBP_R13_REG_mask.Remove(OptoReg::as_OptoReg(r13->as_VMReg())); + _LONG_NO_RBP_R13_REG_mask.Remove(OptoReg::as_OptoReg(r13->as_VMReg()->next())); + _INT_REG_mask = _ALL_INT_REG_mask; if (PreserveFramePointer) { _INT_REG_mask.Remove(OptoReg::as_OptoReg(rbp->as_VMReg())); @@ -427,6 +447,10 @@ void reg_mask_init() { _INT_NO_RCX_REG_mask = _INT_REG_mask; _INT_NO_RCX_REG_mask.Remove(OptoReg::as_OptoReg(rcx->as_VMReg())); + _INT_NO_RBP_R13_REG_mask = _INT_REG_mask; + _INT_NO_RBP_R13_REG_mask.Remove(OptoReg::as_OptoReg(rbp->as_VMReg())); + _INT_NO_RBP_R13_REG_mask.Remove(OptoReg::as_OptoReg(r13->as_VMReg())); + // _FLOAT_REG_LEGACY_mask/_FLOAT_REG_EVEX_mask is generated by adlc // from the float_reg_legacy/float_reg_evex register class. _FLOAT_REG_mask = VM_Version::supports_evex() ? _FLOAT_REG_EVEX_mask : _FLOAT_REG_LEGACY_mask; @@ -1926,7 +1950,7 @@ encode %{ Label done; // cmp $0x80000000,%eax - __ cmp(as_Register(RAX_enc), 0x80000000); + __ cmpl(as_Register(RAX_enc), 0x80000000); // jne e __ jccb(Assembler::notEqual, normal); @@ -3491,6 +3515,21 @@ operand no_rax_rdx_RegI() interface(REG_INTER); %} +operand no_rbp_r13_RegI() +%{ + constraint(ALLOC_IN_RC(int_no_rbp_r13_reg)); + match(RegI); + match(rRegI); + match(rax_RegI); + match(rbx_RegI); + match(rcx_RegI); + match(rdx_RegI); + match(rdi_RegI); + + format %{ %} + interface(REG_INTER); +%} + // Pointer Register operand any_RegP() %{ @@ -3718,6 +3757,19 @@ operand rdx_RegL() interface(REG_INTER); %} +operand no_rbp_r13_RegL() +%{ + constraint(ALLOC_IN_RC(long_no_rbp_r13_reg)); + match(RegL); + match(rRegL); + match(rax_RegL); + match(rcx_RegL); + match(rdx_RegL); + + format %{ %} + interface(REG_INTER); +%} + // Flags register, used as output of compare instructions operand rFlagsReg() %{ @@ -7443,14 +7495,53 @@ instruct decI_mem(memory dst, immI_M1 src, rFlagsReg cr) ins_pipe(ialu_mem_imm); %} -instruct leaI_rReg_immI(rRegI dst, rRegI src0, immI src1) +instruct leaI_rReg_immI2_immI(rRegI dst, rRegI index, immI2 scale, immI disp) %{ - match(Set dst (AddI src0 src1)); + predicate(VM_Version::supports_fast_2op_lea()); + match(Set dst (AddI (LShiftI index scale) disp)); - ins_cost(110); - format %{ "addr32 leal $dst, [$src0 + $src1]\t# int" %} + format %{ "leal $dst, [$index << $scale + $disp]\t# int" %} + ins_encode %{ + Address::ScaleFactor scale = static_cast($scale$$constant); + __ leal($dst$$Register, Address(noreg, $index$$Register, scale, $disp$$constant)); + %} + ins_pipe(ialu_reg_reg); +%} + +instruct leaI_rReg_rReg_immI(rRegI dst, rRegI base, rRegI index, immI disp) +%{ + predicate(VM_Version::supports_fast_3op_lea()); + match(Set dst (AddI (AddI base index) disp)); + + format %{ "leal $dst, [$base + $index + $disp]\t# int" %} ins_encode %{ - __ leal($dst$$Register, Address($src0$$Register, $src1$$constant)); + __ leal($dst$$Register, Address($base$$Register, $index$$Register, Address::times_1, $disp$$constant)); + %} + ins_pipe(ialu_reg_reg); +%} + +instruct leaI_rReg_rReg_immI2(rRegI dst, no_rbp_r13_RegI base, rRegI index, immI2 scale) +%{ + predicate(VM_Version::supports_fast_2op_lea()); + match(Set dst (AddI base (LShiftI index scale))); + + format %{ "leal $dst, [$base + $index << $scale]\t# int" %} + ins_encode %{ + Address::ScaleFactor scale = static_cast($scale$$constant); + __ leal($dst$$Register, Address($base$$Register, $index$$Register, scale)); + %} + ins_pipe(ialu_reg_reg); +%} + +instruct leaI_rReg_rReg_immI2_immI(rRegI dst, rRegI base, rRegI index, immI2 scale, immI disp) +%{ + predicate(VM_Version::supports_fast_3op_lea()); + match(Set dst (AddI (AddI base (LShiftI index scale)) disp)); + + format %{ "leal $dst, [$base + $index << $scale + $disp]\t# int" %} + ins_encode %{ + Address::ScaleFactor scale = static_cast($scale$$constant); + __ leal($dst$$Register, Address($base$$Register, $index$$Register, scale, $disp$$constant)); %} ins_pipe(ialu_reg_reg); %} @@ -7574,14 +7665,53 @@ instruct decL_mem(memory dst, immL_M1 src, rFlagsReg cr) ins_pipe(ialu_mem_imm); %} -instruct leaL_rReg_immL(rRegL dst, rRegL src0, immL32 src1) +instruct leaL_rReg_immI2_immL32(rRegL dst, rRegL index, immI2 scale, immL32 disp) %{ - match(Set dst (AddL src0 src1)); + predicate(VM_Version::supports_fast_2op_lea()); + match(Set dst (AddL (LShiftL index scale) disp)); - ins_cost(110); - format %{ "leaq $dst, [$src0 + $src1]\t# long" %} + format %{ "leaq $dst, [$index << $scale + $disp]\t# long" %} + ins_encode %{ + Address::ScaleFactor scale = static_cast($scale$$constant); + __ leaq($dst$$Register, Address(noreg, $index$$Register, scale, $disp$$constant)); + %} + ins_pipe(ialu_reg_reg); +%} + +instruct leaL_rReg_rReg_immL32(rRegL dst, rRegL base, rRegL index, immL32 disp) +%{ + predicate(VM_Version::supports_fast_3op_lea()); + match(Set dst (AddL (AddL base index) disp)); + + format %{ "leaq $dst, [$base + $index + $disp]\t# long" %} + ins_encode %{ + __ leaq($dst$$Register, Address($base$$Register, $index$$Register, Address::times_1, $disp$$constant)); + %} + ins_pipe(ialu_reg_reg); +%} + +instruct leaL_rReg_rReg_immI2(rRegL dst, no_rbp_r13_RegL base, rRegL index, immI2 scale) +%{ + predicate(VM_Version::supports_fast_2op_lea()); + match(Set dst (AddL base (LShiftL index scale))); + + format %{ "leaq $dst, [$base + $index << $scale]\t# long" %} + ins_encode %{ + Address::ScaleFactor scale = static_cast($scale$$constant); + __ leaq($dst$$Register, Address($base$$Register, $index$$Register, scale)); + %} + ins_pipe(ialu_reg_reg); +%} + +instruct leaL_rReg_rReg_immI2_immL32(rRegL dst, rRegL base, rRegL index, immI2 scale, immL32 disp) +%{ + predicate(VM_Version::supports_fast_3op_lea()); + match(Set dst (AddL (AddL base (LShiftL index scale)) disp)); + + format %{ "leaq $dst, [$base + $index << $scale + $disp]\t# long" %} ins_encode %{ - __ leaq($dst$$Register, Address($src0$$Register, $src1$$constant)); + Address::ScaleFactor scale = static_cast($scale$$constant); + __ leaq($dst$$Register, Address($base$$Register, $index$$Register, scale, $disp$$constant)); %} ins_pipe(ialu_reg_reg); %} @@ -7612,18 +7742,6 @@ instruct addP_rReg_imm(rRegP dst, immL32 src, rFlagsReg cr) // XXX addP mem ops ???? -instruct leaP_rReg_imm(rRegP dst, rRegP src0, immL32 src1) -%{ - match(Set dst (AddP src0 src1)); - - ins_cost(110); - format %{ "leaq $dst, [$src0 + $src1]\t# ptr" %} - ins_encode %{ - __ leaq($dst$$Register, Address($src0$$Register, $src1$$constant)); - %} - ins_pipe(ialu_reg_reg); -%} - instruct checkCastPP(rRegP dst) %{ match(Set dst (CheckCastPP dst)); @@ -11685,34 +11803,34 @@ instruct array_equalsC_evex(rdi_RegP ary1, rsi_RegP ary2, rax_RegI result, ins_pipe( pipe_slow ); %} -instruct has_negatives(rsi_RegP ary1, rcx_RegI len, rax_RegI result, - legRegD tmp1, legRegD tmp2, rbx_RegI tmp3, rFlagsReg cr,) +instruct count_positives(rsi_RegP ary1, rcx_RegI len, rax_RegI result, + legRegD tmp1, legRegD tmp2, rbx_RegI tmp3, rFlagsReg cr,) %{ predicate(!VM_Version::supports_avx512vlbw() || !VM_Version::supports_bmi2()); - match(Set result (HasNegatives ary1 len)); + match(Set result (CountPositives ary1 len)); effect(TEMP tmp1, TEMP tmp2, USE_KILL ary1, USE_KILL len, KILL tmp3, KILL cr); - format %{ "has negatives byte[] $ary1,$len -> $result // KILL $tmp1, $tmp2, $tmp3" %} + format %{ "countPositives byte[] $ary1,$len -> $result // KILL $tmp1, $tmp2, $tmp3" %} ins_encode %{ - __ has_negatives($ary1$$Register, $len$$Register, - $result$$Register, $tmp3$$Register, - $tmp1$$XMMRegister, $tmp2$$XMMRegister, knoreg, knoreg); + __ count_positives($ary1$$Register, $len$$Register, + $result$$Register, $tmp3$$Register, + $tmp1$$XMMRegister, $tmp2$$XMMRegister, knoreg, knoreg); %} ins_pipe( pipe_slow ); %} -instruct has_negatives_evex(rsi_RegP ary1, rcx_RegI len, rax_RegI result, - legRegD tmp1, legRegD tmp2, kReg ktmp1, kReg ktmp2, rbx_RegI tmp3, rFlagsReg cr,) +instruct count_positives_evex(rsi_RegP ary1, rcx_RegI len, rax_RegI result, + legRegD tmp1, legRegD tmp2, kReg ktmp1, kReg ktmp2, rbx_RegI tmp3, rFlagsReg cr,) %{ predicate(VM_Version::supports_avx512vlbw() && VM_Version::supports_bmi2()); - match(Set result (HasNegatives ary1 len)); + match(Set result (CountPositives ary1 len)); effect(TEMP tmp1, TEMP tmp2, TEMP ktmp1, TEMP ktmp2, USE_KILL ary1, USE_KILL len, KILL tmp3, KILL cr); - format %{ "has negatives byte[] $ary1,$len -> $result // KILL $tmp1, $tmp2, $tmp3" %} + format %{ "countPositives byte[] $ary1,$len -> $result // KILL $tmp1, $tmp2, $tmp3" %} ins_encode %{ - __ has_negatives($ary1$$Register, $len$$Register, - $result$$Register, $tmp3$$Register, - $tmp1$$XMMRegister, $tmp2$$XMMRegister, $ktmp1$$KRegister, $ktmp2$$KRegister); + __ count_positives($ary1$$Register, $len$$Register, + $result$$Register, $tmp3$$Register, + $tmp1$$XMMRegister, $tmp2$$XMMRegister, $ktmp1$$KRegister, $ktmp2$$KRegister); %} ins_pipe( pipe_slow ); %} diff --git a/src/hotspot/cpu/zero/copy_zero.hpp b/src/hotspot/cpu/zero/copy_zero.hpp index e45e598f74c92494cd8f8ff04763585ec19524c5..1594e861535f850371403be20c9516f3a828e151 100644 --- a/src/hotspot/cpu/zero/copy_zero.hpp +++ b/src/hotspot/cpu/zero/copy_zero.hpp @@ -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. * Copyright 2007 Red Hat, Inc. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -52,22 +52,7 @@ static void pd_disjoint_words(const HeapWord* from, HeapWord* to, size_t count) static void pd_disjoint_words_atomic(const HeapWord* from, HeapWord* to, size_t count) { - switch (count) { - case 8: to[7] = from[7]; - case 7: to[6] = from[6]; - case 6: to[5] = from[5]; - case 5: to[4] = from[4]; - case 4: to[3] = from[3]; - case 3: to[2] = from[2]; - case 2: to[1] = from[1]; - case 1: to[0] = from[0]; - case 0: break; - default: - while (count-- > 0) { - *to++ = *from++; - } - break; - } + shared_disjoint_words_atomic(from, to, count); } static void pd_aligned_conjoint_words(const HeapWord* from, diff --git a/src/hotspot/cpu/zero/frame_zero.inline.hpp b/src/hotspot/cpu/zero/frame_zero.inline.hpp index 396e189a5db4039fbf03ca242a56919e524d4354..dfca0e4bcb11c4f9bbc08d09a6d791f566430ae5 100644 --- a/src/hotspot/cpu/zero/frame_zero.inline.hpp +++ b/src/hotspot/cpu/zero/frame_zero.inline.hpp @@ -82,6 +82,11 @@ inline intptr_t* frame::link() const { return NULL; } +inline intptr_t* frame::link_or_null() const { + ShouldNotCallThis(); + return NULL; +} + inline interpreterState frame::get_interpreterState() const { return zero_interpreterframe()->interpreter_state(); } diff --git a/src/hotspot/os/aix/attachListener_aix.cpp b/src/hotspot/os/aix/attachListener_aix.cpp index 25dfe8d816b609cff331213d80d7c892cad32716..461b7fc874f46dc20985019192355b3709aeee5e 100644 --- a/src/hotspot/os/aix/attachListener_aix.cpp +++ b/src/hotspot/os/aix/attachListener_aix.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2022, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2012, 2018 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -28,7 +28,6 @@ #include "runtime/interfaceSupport.inline.hpp" #include "runtime/os.inline.hpp" #include "services/attachListener.hpp" -#include "services/dtraceAttacher.hpp" #include #include diff --git a/src/hotspot/os/bsd/attachListener_bsd.cpp b/src/hotspot/os/bsd/attachListener_bsd.cpp index 9daad43dc7ad567dd87c9ce44b1363d18c4f5931..b8702c5aa763ef87658db1c1a77b898620d42459 100644 --- a/src/hotspot/os/bsd/attachListener_bsd.cpp +++ b/src/hotspot/os/bsd/attachListener_bsd.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2021, 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 @@ -27,7 +27,6 @@ #include "runtime/interfaceSupport.inline.hpp" #include "runtime/os.inline.hpp" #include "services/attachListener.hpp" -#include "services/dtraceAttacher.hpp" #include #include diff --git a/src/hotspot/os/bsd/threadCritical_bsd.cpp b/src/hotspot/os/bsd/threadCritical_bsd.cpp deleted file mode 100644 index 71c51df599d7bcf7c6592f9bfa44a2bb1f245fc0..0000000000000000000000000000000000000000 --- a/src/hotspot/os/bsd/threadCritical_bsd.cpp +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved. - * 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 "precompiled.hpp" -#include "runtime/thread.inline.hpp" -#include "runtime/threadCritical.hpp" - -// put OS-includes here -# include - -// -// See threadCritical.hpp for details of this class. -// - -static pthread_t tc_owner = 0; -static pthread_mutex_t tc_mutex = PTHREAD_MUTEX_INITIALIZER; -static int tc_count = 0; - -ThreadCritical::ThreadCritical() { - pthread_t self = pthread_self(); - if (self != tc_owner) { - int ret = pthread_mutex_lock(&tc_mutex); - guarantee(ret == 0, "fatal error with pthread_mutex_lock()"); - assert(tc_count == 0, "Lock acquired with illegal reentry count."); - tc_owner = self; - } - tc_count++; -} - -ThreadCritical::~ThreadCritical() { - assert(tc_owner == pthread_self(), "must have correct owner"); - assert(tc_count > 0, "must have correct count"); - - tc_count--; - if (tc_count == 0) { - tc_owner = 0; - int ret = pthread_mutex_unlock(&tc_mutex); - guarantee(ret == 0, "fatal error with pthread_mutex_unlock()"); - } -} diff --git a/src/hotspot/os/linux/attachListener_linux.cpp b/src/hotspot/os/linux/attachListener_linux.cpp index eb723603b5f19e509bc1f0f9e2035805e714b8c9..a6ab0ae8c943d64643a757cf07a0ecf914e61e15 100644 --- a/src/hotspot/os/linux/attachListener_linux.cpp +++ b/src/hotspot/os/linux/attachListener_linux.cpp @@ -28,7 +28,6 @@ #include "runtime/interfaceSupport.inline.hpp" #include "runtime/os.inline.hpp" #include "services/attachListener.hpp" -#include "services/dtraceAttacher.hpp" #include #include diff --git a/src/hotspot/os/linux/cgroupSubsystem_linux.cpp b/src/hotspot/os/linux/cgroupSubsystem_linux.cpp index dd858a30e4cdf3b7354d02d59a2a434ec4a3d97c..1346cf8915f111729f9aa7f99d06bac705fba7da 100644 --- a/src/hotspot/os/linux/cgroupSubsystem_linux.cpp +++ b/src/hotspot/os/linux/cgroupSubsystem_linux.cpp @@ -495,7 +495,12 @@ int CgroupSubsystem::active_processor_count() { cpu_count = limit_count = os::Linux::active_processor_count(); int quota = cpu_quota(); int period = cpu_period(); - int share = cpu_shares(); + + // It's not a good idea to use cpu_shares() to limit the number + // of CPUs used by the JVM. See JDK-8281181. + // UseContainerCpuShares and PreferContainerQuotaForCPUCount are + // deprecated and will be removed in the next JDK release. + int share = UseContainerCpuShares ? cpu_shares() : -1; if (quota > -1 && period > 0) { quota_count = ceilf((float)quota / (float)period); diff --git a/src/hotspot/os/linux/globals_linux.hpp b/src/hotspot/os/linux/globals_linux.hpp index 72915b5afbbbe38d25dc624a48685cb09d7fe2f5..2fc4a404b3411244e8acb26c8f767d264fed4d91 100644 --- a/src/hotspot/os/linux/globals_linux.hpp +++ b/src/hotspot/os/linux/globals_linux.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2020, 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 @@ -59,10 +59,14 @@ product(bool, UseContainerSupport, true, \ "Enable detection and runtime container configuration support") \ \ + product(bool, UseContainerCpuShares, false, \ + "(Deprecated) Include CPU shares in the CPU availability" \ + " calculation.") \ + \ product(bool, PreferContainerQuotaForCPUCount, true, \ - "Calculate the container CPU availability based on the value" \ - " of quotas (if set), when true. Otherwise, use the CPU" \ - " shares value, provided it is less than quota.") \ + "(Deprecated) Calculate the container CPU availability based" \ + " on the value of quotas (if set), when true. Otherwise, use" \ + " the CPU shares value, provided it is less than quota.") \ \ product(bool, AdjustStackSizeForTLS, false, \ "Increase the thread stack size to include space for glibc " \ diff --git a/src/hotspot/os/linux/os_linux.cpp b/src/hotspot/os/linux/os_linux.cpp index 18b908cfc8fc0eec9e0369b342807920521158de..f2ecca92c82834f5a455e003bd3e429134e75067 100644 --- a/src/hotspot/os/linux/os_linux.cpp +++ b/src/hotspot/os/linux/os_linux.cpp @@ -1,5 +1,6 @@ /* * Copyright (c) 1999, 2022, 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. * * This code is free software; you can redistribute it and/or modify it @@ -2092,6 +2093,34 @@ bool os::Linux::query_process_memory_info(os::Linux::meminfo_t* info) { return false; } +#ifdef __GLIBC__ +// For Glibc, print a one-liner with the malloc tunables. +// Most important and popular is MALLOC_ARENA_MAX, but we are +// thorough and print them all. +static void print_glibc_malloc_tunables(outputStream* st) { + static const char* var[] = { + // the new variant + "GLIBC_TUNABLES", + // legacy variants + "MALLOC_CHECK_", "MALLOC_TOP_PAD_", "MALLOC_PERTURB_", + "MALLOC_MMAP_THRESHOLD_", "MALLOC_TRIM_THRESHOLD_", + "MALLOC_MMAP_MAX_", "MALLOC_ARENA_TEST", "MALLOC_ARENA_MAX", + NULL}; + st->print("glibc malloc tunables: "); + bool printed = false; + for (int i = 0; var[i] != NULL; i ++) { + const char* const val = ::getenv(var[i]); + if (val != NULL) { + st->print("%s%s=%s", (printed ? ", " : ""), var[i], val); + printed = true; + } + } + if (!printed) { + st->print("(default)"); + } +} +#endif // __GLIBC__ + void os::Linux::print_process_memory_info(outputStream* st) { st->print_cr("Process Memory:"); @@ -2114,8 +2143,9 @@ void os::Linux::print_process_memory_info(outputStream* st) { st->print_cr("Could not open /proc/self/status to get process memory related information"); } - // Print glibc outstanding allocations. - // (note: there is no implementation of mallinfo for muslc) + // glibc only: + // - Print outstanding allocations using mallinfo + // - Print glibc tunables #ifdef __GLIBC__ size_t total_allocated = 0; bool might_have_wrapped = false; @@ -2123,9 +2153,10 @@ void os::Linux::print_process_memory_info(outputStream* st) { struct glibc_mallinfo2 mi = _mallinfo2(); total_allocated = mi.uordblks; } else if (_mallinfo != NULL) { - // mallinfo is an old API. Member names mean next to nothing and, beyond that, are int. - // So values may have wrapped around. Still useful enough to see how much glibc thinks - // we allocated. + // mallinfo is an old API. Member names mean next to nothing and, beyond that, are 32-bit signed. + // So for larger footprints the values may have wrapped around. We try to detect this here: if the + // process whole resident set size is smaller than 4G, malloc footprint has to be less than that + // and the numbers are reliable. struct glibc_mallinfo mi = _mallinfo(); total_allocated = (size_t)(unsigned)mi.uordblks; // Since mallinfo members are int, glibc values may have wrapped. Warn about this. @@ -2136,8 +2167,10 @@ void os::Linux::print_process_memory_info(outputStream* st) { total_allocated / K, might_have_wrapped ? " (may have wrapped)" : ""); } -#endif // __GLIBC__ - + // Tunables + print_glibc_malloc_tunables(st); + st->cr(); +#endif } bool os::Linux::print_ld_preload_file(outputStream* st) { @@ -3939,23 +3972,14 @@ char* os::Linux::reserve_memory_special_shm(size_t bytes, size_t alignment, return addr; } -static void warn_on_commit_special_failure(char* req_addr, size_t bytes, +static void log_on_commit_special_failure(char* req_addr, size_t bytes, size_t page_size, int error) { assert(error == ENOMEM, "Only expect to fail if no memory is available"); - bool warn_on_failure = UseLargePages && - (!FLAG_IS_DEFAULT(UseLargePages) || - !FLAG_IS_DEFAULT(UseHugeTLBFS) || - !FLAG_IS_DEFAULT(LargePageSizeInBytes)); - - if (warn_on_failure) { - char msg[128]; - jio_snprintf(msg, sizeof(msg), "Failed to reserve and commit memory. req_addr: " - PTR_FORMAT " bytes: " SIZE_FORMAT " page size: " - SIZE_FORMAT " (errno = %d).", - req_addr, bytes, page_size, error); - warning("%s", msg); - } + log_info(pagesize)("Failed to reserve and commit memory with given page size. req_addr: " PTR_FORMAT + " size: " SIZE_FORMAT "%s, page size: " SIZE_FORMAT "%s, (errno = %d)", + p2i(req_addr), byte_size_in_exact_unit(bytes), exact_unit_for_byte_size(bytes), + byte_size_in_exact_unit(page_size), exact_unit_for_byte_size(page_size), error); } bool os::Linux::commit_memory_special(size_t bytes, @@ -3977,7 +4001,7 @@ bool os::Linux::commit_memory_special(size_t bytes, char* addr = (char*)::mmap(req_addr, bytes, prot, flags, -1, 0); if (addr == MAP_FAILED) { - warn_on_commit_special_failure(req_addr, bytes, page_size, errno); + log_on_commit_special_failure(req_addr, bytes, page_size, errno); return false; } diff --git a/src/hotspot/os/linux/threadCritical_linux.cpp b/src/hotspot/os/linux/threadCritical_linux.cpp deleted file mode 100644 index 71c51df599d7bcf7c6592f9bfa44a2bb1f245fc0..0000000000000000000000000000000000000000 --- a/src/hotspot/os/linux/threadCritical_linux.cpp +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved. - * 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 "precompiled.hpp" -#include "runtime/thread.inline.hpp" -#include "runtime/threadCritical.hpp" - -// put OS-includes here -# include - -// -// See threadCritical.hpp for details of this class. -// - -static pthread_t tc_owner = 0; -static pthread_mutex_t tc_mutex = PTHREAD_MUTEX_INITIALIZER; -static int tc_count = 0; - -ThreadCritical::ThreadCritical() { - pthread_t self = pthread_self(); - if (self != tc_owner) { - int ret = pthread_mutex_lock(&tc_mutex); - guarantee(ret == 0, "fatal error with pthread_mutex_lock()"); - assert(tc_count == 0, "Lock acquired with illegal reentry count."); - tc_owner = self; - } - tc_count++; -} - -ThreadCritical::~ThreadCritical() { - assert(tc_owner == pthread_self(), "must have correct owner"); - assert(tc_count > 0, "must have correct count"); - - tc_count--; - if (tc_count == 0) { - tc_owner = 0; - int ret = pthread_mutex_unlock(&tc_mutex); - guarantee(ret == 0, "fatal error with pthread_mutex_unlock()"); - } -} diff --git a/src/hotspot/os/posix/signals_posix.cpp b/src/hotspot/os/posix/signals_posix.cpp index 895c3cc09ae88c5d7ec04c57e8716062b46a707a..6e94b47712f95f9194a3d4a3a138eec629b9535e 100644 --- a/src/hotspot/os/posix/signals_posix.cpp +++ b/src/hotspot/os/posix/signals_posix.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 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 @@ -1556,8 +1556,6 @@ void PosixSignals::hotspot_sigmask(Thread* thread) { // - Forte Analyzer: AsyncGetCallTrace() // - StackBanging: get_frame_at_stack_banging_point() -sigset_t SR_sigset; - static void resume_clear_context(OSThread *osthread) { osthread->set_ucontext(NULL); osthread->set_siginfo(NULL); @@ -1673,14 +1671,11 @@ int SR_initialize() { assert(PosixSignals::SR_signum > SIGSEGV && PosixSignals::SR_signum > SIGBUS, "SR_signum must be greater than max(SIGSEGV, SIGBUS), see 4355769"); - sigemptyset(&SR_sigset); - sigaddset(&SR_sigset, PosixSignals::SR_signum); - // Set up signal handler for suspend/resume act.sa_flags = SA_RESTART|SA_SIGINFO; act.sa_handler = (void (*)(int)) SR_handler; - // SR_signum is blocked by default. + // SR_signum is blocked when the handler runs. pthread_sigmask(SIG_BLOCK, NULL, &act.sa_mask); remove_error_signals_from_set(&(act.sa_mask)); diff --git a/src/hotspot/os/aix/threadCritical_aix.cpp b/src/hotspot/os/posix/threadCritical_posix.cpp similarity index 96% rename from src/hotspot/os/aix/threadCritical_aix.cpp rename to src/hotspot/os/posix/threadCritical_posix.cpp index cd25cb68dc4646e54a6ff89b01afc73377dcfbe6..ee57352cb0cbef007055a2cc25148f3794dba055 100644 --- a/src/hotspot/os/aix/threadCritical_aix.cpp +++ b/src/hotspot/os/posix/threadCritical_posix.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2022, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2012, 2014 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -24,8 +24,8 @@ */ #include "precompiled.hpp" -#include "runtime/threadCritical.hpp" #include "runtime/thread.inline.hpp" +#include "runtime/threadCritical.hpp" // put OS-includes here # include diff --git a/src/hotspot/os/windows/attachListener_windows.cpp b/src/hotspot/os/windows/attachListener_windows.cpp index 8b5a2cb7ab4fb8e1bc9f9f209a9e4f8028c6cff1..710afc410051f627ff45807be7454e948e263a8b 100644 --- a/src/hotspot/os/windows/attachListener_windows.cpp +++ b/src/hotspot/os/windows/attachListener_windows.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2021, 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 @@ -27,7 +27,6 @@ #include "runtime/interfaceSupport.inline.hpp" #include "runtime/os.hpp" #include "services/attachListener.hpp" -#include "services/dtraceAttacher.hpp" #include #include // SIGBREAK diff --git a/src/hotspot/os/windows/os_windows.cpp b/src/hotspot/os/windows/os_windows.cpp index ed4ba3e1fc2ce3074c31fbd2dc7d9e31d8bc5e8c..fd64008ab48e2851eeced4cfa203d0c05ba983d2 100644 --- a/src/hotspot/os/windows/os_windows.cpp +++ b/src/hotspot/os/windows/os_windows.cpp @@ -4458,7 +4458,7 @@ static errno_t get_full_path(LPCWSTR unicode_path, LPWSTR* full_path) { return ERROR_SUCCESS; } -static void set_path_prefix(char* buf, LPWSTR* prefix, int* prefix_off, bool* needs_fullpath) { +static void set_path_prefix(char* buf, LPCWSTR* prefix, int* prefix_off, bool* needs_fullpath) { *prefix_off = 0; *needs_fullpath = true; @@ -4494,7 +4494,7 @@ static wchar_t* wide_abs_unc_path(char const* path, errno_t & err, int additiona strncpy(buf, path, buf_len); os::native_path(buf); - LPWSTR prefix = NULL; + LPCWSTR prefix = NULL; int prefix_off = 0; bool needs_fullpath = true; set_path_prefix(buf, &prefix, &prefix_off, &needs_fullpath); diff --git a/src/hotspot/os_cpu/bsd_aarch64/pauth_bsd_aarch64.inline.hpp b/src/hotspot/os_cpu/bsd_aarch64/pauth_bsd_aarch64.inline.hpp index a4d416d384e29f2d5daedd76611ce78cfc456e54..4d07bbef3033240d42775dd24ac0db729a7ba46d 100644 --- a/src/hotspot/os_cpu/bsd_aarch64/pauth_bsd_aarch64.inline.hpp +++ b/src/hotspot/os_cpu/bsd_aarch64/pauth_bsd_aarch64.inline.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, Arm Limited. All rights reserved. + * Copyright (c) 2021, 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 @@ -25,29 +25,23 @@ #ifndef OS_CPU_BSD_AARCH64_PAUTH_BSD_AARCH64_INLINE_HPP #define OS_CPU_BSD_AARCH64_PAUTH_BSD_AARCH64_INLINE_HPP -#ifdef __APPLE__ -#include -#endif - -// Only the PAC instructions in the NOP space can be used. This ensures the -// binaries work on systems without PAC. Write these instructions using their -// alternate "hint" instructions to ensure older compilers can still be used. -// For Apple, use the provided interface as this may provide additional -// optimization. - -#define XPACLRI "hint #0x7;" +// OS specific Support for ROP Protection in VM code. +// For more details on PAC see pauth_aarch64.hpp. inline address pauth_strip_pointer(address ptr) { -#ifdef __APPLE__ - return ptrauth_strip(ptr, ptrauth_key_asib); -#else - register address result __asm__("x30") = ptr; - asm (XPACLRI : "+r"(result)); - return result; -#endif + // No PAC support in BSD as of yet. + return ptr; } -#undef XPACLRI +inline address pauth_sign_return_address(address ret_addr, address sp) { + // No PAC support in BSD as of yet. + return ret_addr; +} + +inline address pauth_authenticate_return_address(address ret_addr, address sp) { + // No PAC support in BSD as of yet. + return ret_addr; +} #endif // OS_CPU_BSD_AARCH64_PAUTH_BSD_AARCH64_INLINE_HPP diff --git a/src/hotspot/os_cpu/linux_aarch64/pauth_linux_aarch64.inline.hpp b/src/hotspot/os_cpu/linux_aarch64/pauth_linux_aarch64.inline.hpp index 6f3fd41539c62d430633af1e464fdb058bd9f090..1eb1b92b9365ce23a16dc69351ae9e8815c64851 100644 --- a/src/hotspot/os_cpu/linux_aarch64/pauth_linux_aarch64.inline.hpp +++ b/src/hotspot/os_cpu/linux_aarch64/pauth_linux_aarch64.inline.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, Arm Limited. All rights reserved. + * Copyright (c) 2021, 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 @@ -25,18 +25,57 @@ #ifndef OS_CPU_LINUX_AARCH64_PAUTH_LINUX_AARCH64_INLINE_HPP #define OS_CPU_LINUX_AARCH64_PAUTH_LINUX_AARCH64_INLINE_HPP -// Only the PAC instructions in the NOP space can be used. This ensures the -// binaries work on systems without PAC. Write these instructions using their -// alternate "hint" instructions to ensure older compilers can still be used. +// OS specific Support for ROP Protection in VM code. +// For more details on PAC see pauth_aarch64.hpp. -#define XPACLRI "hint #0x7;" +inline bool pauth_ptr_is_raw(address ptr); +// Use only the PAC instructions in the NOP space. This ensures the binaries work on systems +// without PAC. Write these instructions using their alternate "hint" instructions to ensure older +// compilers can still be used. +#define XPACLRI "hint #0x7;" +#define PACIA1716 "hint #0x8;" +#define AUTIA1716 "hint #0xc;" + +// Strip an address. Use with caution - only if there is no guaranteed way of authenticating the +// value. +// inline address pauth_strip_pointer(address ptr) { register address result __asm__("x30") = ptr; asm (XPACLRI : "+r"(result)); return result; } +// Sign a return value, using the given modifier. +// +inline address pauth_sign_return_address(address ret_addr, address sp) { + if (VM_Version::use_rop_protection()) { + // A pointer cannot be double signed. + guarantee(pauth_ptr_is_raw(ret_addr), "Return address is already signed"); + register address r17 __asm("r17") = ret_addr; + register address r16 __asm("r16") = sp; + asm (PACIA1716 : "+r"(r17) : "r"(r16)); + ret_addr = r17; + } + return ret_addr; +} + +// Authenticate a return value, using the given modifier. +// +inline address pauth_authenticate_return_address(address ret_addr, address sp) { + if (VM_Version::use_rop_protection()) { + register address r17 __asm("r17") = ret_addr; + register address r16 __asm("r16") = sp; + asm (AUTIA1716 : "+r"(r17) : "r"(r16)); + ret_addr = r17; + // Ensure that the pointer authenticated. + guarantee(pauth_ptr_is_raw(ret_addr), "Return address did not authenticate"); + } + return ret_addr; +} + #undef XPACLRI +#undef PACIA1716 +#undef AUTIA1716 #endif // OS_CPU_LINUX_AARCH64_PAUTH_LINUX_AARCH64_INLINE_HPP diff --git a/src/hotspot/os_cpu/linux_aarch64/threadLS_linux_aarch64.S b/src/hotspot/os_cpu/linux_aarch64/threadLS_linux_aarch64.S index f541844b9d6dfd9d230ad73d0f19184731139af6..ac60d6aa941689c1b74a9fa6758cf11dded26df7 100644 --- a/src/hotspot/os_cpu/linux_aarch64/threadLS_linux_aarch64.S +++ b/src/hotspot/os_cpu/linux_aarch64/threadLS_linux_aarch64.S @@ -1,4 +1,4 @@ -// Copyright (c) 2015, Red Hat Inc. All rights reserved. +// Copyright (c) 2015, 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 @@ -29,6 +29,7 @@ .type _ZN10JavaThread25aarch64_get_thread_helperEv, %function _ZN10JavaThread25aarch64_get_thread_helperEv: + hint #0x19 // paciasp stp x29, x30, [sp, -16]! adrp x0, :tlsdesc:_ZN6Thread12_thr_currentE ldr x1, [x0, #:tlsdesc_lo12:_ZN6Thread12_thr_currentE] @@ -39,6 +40,7 @@ _ZN10JavaThread25aarch64_get_thread_helperEv: add x0, x1, x0 ldr x0, [x0] ldp x29, x30, [sp], 16 + hint #0x1d // autiasp ret .size _ZN10JavaThread25aarch64_get_thread_helperEv, .-_ZN10JavaThread25aarch64_get_thread_helperEv diff --git a/src/hotspot/os_cpu/linux_aarch64/vm_version_linux_aarch64.cpp b/src/hotspot/os_cpu/linux_aarch64/vm_version_linux_aarch64.cpp index b5f5a0787e91ab611b1f9dbe0cb383c5796cec9e..b1080e77c908cf0bfdc63a77a42016e6d1a0de32 100644 --- a/src/hotspot/os_cpu/linux_aarch64/vm_version_linux_aarch64.cpp +++ b/src/hotspot/os_cpu/linux_aarch64/vm_version_linux_aarch64.cpp @@ -72,6 +72,10 @@ #define HWCAP_SVE (1 << 22) #endif +#ifndef HWCAP_PACA +#define HWCAP_PACA (1 << 30) +#endif + #ifndef HWCAP2_SVE2 #define HWCAP2_SVE2 (1 << 1) #endif @@ -111,6 +115,7 @@ void VM_Version::get_os_cpu_info() { static_assert(CPU_SHA3 == HWCAP_SHA3, "Flag CPU_SHA3 must follow Linux HWCAP"); static_assert(CPU_SHA512 == HWCAP_SHA512, "Flag CPU_SHA512 must follow Linux HWCAP"); static_assert(CPU_SVE == HWCAP_SVE, "Flag CPU_SVE must follow Linux HWCAP"); + static_assert(CPU_PACA == HWCAP_PACA, "Flag CPU_PACA must follow Linux HWCAP"); _features = auxv & ( HWCAP_FP | HWCAP_ASIMD | @@ -124,7 +129,8 @@ void VM_Version::get_os_cpu_info() { HWCAP_DCPOP | HWCAP_SHA3 | HWCAP_SHA512 | - HWCAP_SVE); + HWCAP_SVE | + HWCAP_PACA); if (auxv2 & HWCAP2_SVE2) _features |= CPU_SVE2; diff --git a/src/hotspot/os_cpu/linux_x86/os_linux_x86.cpp b/src/hotspot/os_cpu/linux_x86/os_linux_x86.cpp index 5e346efee54e0279d03d4d2a7173600192208bf7..c6b945fdd7903e69ed661f5ca1778a511bbc253f 100644 --- a/src/hotspot/os_cpu/linux_x86/os_linux_x86.cpp +++ b/src/hotspot/os_cpu/linux_x86/os_linux_x86.cpp @@ -459,11 +459,26 @@ bool os::supports_sse() { } juint os::cpu_microcode_revision() { + // Note: this code runs on startup, and therefore should not be slow, + // see JDK-8283200. + juint result = 0; - char data[2048] = {0}; // lines should fit in 2K buf - size_t len = sizeof(data); - FILE *fp = os::fopen("/proc/cpuinfo", "r"); + + // Attempt 1 (faster): Read the microcode version off the sysfs. + FILE *fp = os::fopen("/sys/devices/system/cpu/cpu0/microcode/version", "r"); + if (fp) { + int read = fscanf(fp, "%x", &result); + fclose(fp); + if (read > 0) { + return result; + } + } + + // Attempt 2 (slower): Read the microcode version off the procfs. + fp = os::fopen("/proc/cpuinfo", "r"); if (fp) { + char data[2048] = {0}; // lines should fit in 2K buf + size_t len = sizeof(data); while (!feof(fp)) { if (fgets(data, len, fp)) { if (strstr(data, "microcode") != NULL) { @@ -475,6 +490,7 @@ juint os::cpu_microcode_revision() { } fclose(fp); } + return result; } diff --git a/src/hotspot/os_cpu/windows_aarch64/copy_windows_aarch64.hpp b/src/hotspot/os_cpu/windows_aarch64/copy_windows_aarch64.hpp index 2d3c55cea39130770c733dfed20df332433af61f..ce2ad2d046f88ff6b65c4768eecd4e531a974114 100644 --- a/src/hotspot/os_cpu/windows_aarch64/copy_windows_aarch64.hpp +++ b/src/hotspot/os_cpu/windows_aarch64/copy_windows_aarch64.hpp @@ -1,5 +1,6 @@ /* * Copyright (c) 2020, Microsoft Corporation. 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 @@ -49,21 +50,7 @@ static void pd_disjoint_words(const HeapWord* from, HeapWord* to, size_t count) } static void pd_disjoint_words_atomic(const HeapWord* from, HeapWord* to, size_t count) { - switch (count) { - case 8: to[7] = from[7]; - case 7: to[6] = from[6]; - case 6: to[5] = from[5]; - case 5: to[4] = from[4]; - case 4: to[3] = from[3]; - case 3: to[2] = from[2]; - case 2: to[1] = from[1]; - case 1: to[0] = from[0]; - case 0: break; - default: while (count-- > 0) { - *to++ = *from++; - } - break; - } + shared_disjoint_words_atomic(from, to, count); } static void pd_aligned_conjoint_words(const HeapWord* from, HeapWord* to, size_t count) { diff --git a/src/hotspot/os_cpu/windows_aarch64/pauth_windows_aarch64.inline.hpp b/src/hotspot/os_cpu/windows_aarch64/pauth_windows_aarch64.inline.hpp index 844291ee1e41231818704e1a9321632e26f98b50..6b5c9eecb72a49d8caafc4f5c186c47ff0caecc4 100644 --- a/src/hotspot/os_cpu/windows_aarch64/pauth_windows_aarch64.inline.hpp +++ b/src/hotspot/os_cpu/windows_aarch64/pauth_windows_aarch64.inline.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, Arm Limited. All rights reserved. + * Copyright (c) 2021, 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 @@ -25,10 +25,22 @@ #ifndef OS_CPU_WINDOWS_AARCH64_PAUTH_WINDOWS_AARCH64_INLINE_HPP #define OS_CPU_WINDOWS_AARCH64_PAUTH_WINDOWS_AARCH64_INLINE_HPP +// OS specific Support for ROP Protection in VM code. +// For more details on PAC see pauth_aarch64.hpp. + inline address pauth_strip_pointer(address ptr) { // No PAC support in windows as of yet. return ptr; } -#endif // OS_CPU_WINDOWS_AARCH64_PAUTH_WINDOWS_AARCH64_INLINE_HPP +inline address pauth_sign_return_address(address ret_addr, address sp) { + // No PAC support in windows as of yet. + return ret_addr; +} +inline address pauth_authenticate_return_address(address ret_addr, address sp) { + // No PAC support in windows as of yet. + return ret_addr; +} + +#endif // OS_CPU_WINDOWS_AARCH64_PAUTH_WINDOWS_AARCH64_INLINE_HPP diff --git a/src/hotspot/share/adlc/formssel.cpp b/src/hotspot/share/adlc/formssel.cpp index 274e623ea61872c9072d240a718f5a445064b3ed..0ae7b07507436bf982dd2b3fc65ec151d1e5824c 100644 --- a/src/hotspot/share/adlc/formssel.cpp +++ b/src/hotspot/share/adlc/formssel.cpp @@ -612,7 +612,7 @@ bool InstructForm::needs_anti_dependence_check(FormDict &globals) const { strcmp(_matrule->_rChild->_opType,"StrEquals" )==0 || strcmp(_matrule->_rChild->_opType,"StrIndexOf" )==0 || strcmp(_matrule->_rChild->_opType,"StrIndexOfChar" )==0 || - strcmp(_matrule->_rChild->_opType,"HasNegatives" )==0 || + strcmp(_matrule->_rChild->_opType,"CountPositives" )==0 || strcmp(_matrule->_rChild->_opType,"AryEq" )==0 )) return true; @@ -902,7 +902,7 @@ uint InstructForm::oper_input_base(FormDict &globals) { strcmp(_matrule->_rChild->_opType,"StrCompressedCopy" )==0 || strcmp(_matrule->_rChild->_opType,"StrIndexOf")==0 || strcmp(_matrule->_rChild->_opType,"StrIndexOfChar")==0 || - strcmp(_matrule->_rChild->_opType,"HasNegatives")==0 || + strcmp(_matrule->_rChild->_opType,"CountPositives")==0 || strcmp(_matrule->_rChild->_opType,"EncodeISOArray")==0)) { // String.(compareTo/equals/indexOf) and Arrays.equals // and sun.nio.cs.iso8859_1$Encoder.EncodeISOArray diff --git a/src/hotspot/share/asm/register.hpp b/src/hotspot/share/asm/register.hpp index 06a8735f52061c05682bfd6158de1049086eb233..b8538e4df6810330e02f798b8baa4404f4d80c87 100644 --- a/src/hotspot/share/asm/register.hpp +++ b/src/hotspot/share/asm/register.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 @@ -28,6 +28,7 @@ #include "utilities/debug.hpp" #include "utilities/globalDefinitions.hpp" #include "utilities/macros.hpp" +#include "utilities/population_count.hpp" // Use AbstractRegister as shortcut class AbstractRegisterImpl; @@ -36,7 +37,7 @@ typedef AbstractRegisterImpl* AbstractRegister; // The super class for platform specific registers. Instead of using value objects, // registers are implemented as pointers. Subclassing is used so all registers can -// use the debugging suport below. No virtual functions are used for efficiency. +// use the debugging support below. No virtual functions are used for efficiency. // They are canonicalized; i.e., registers are equal if their pointers are equal, // and vice versa. A concrete implementation may just map the register onto 'this'. @@ -86,8 +87,149 @@ const type name = ((type)value) #define INTERNAL_VISIBILITY #endif +template class RegSetIterator; +template class ReverseRegSetIterator; -#define REGISTER_DEFINITION(type, name) +// A set of registers +template +class AbstractRegSet { + uint32_t _bitset; + + AbstractRegSet(uint32_t bitset) : _bitset(bitset) { } + +public: + + AbstractRegSet() : _bitset(0) { } + + AbstractRegSet(RegImpl r1) : _bitset(1 << r1->encoding()) { } + + AbstractRegSet operator+(const AbstractRegSet aSet) const { + AbstractRegSet result(_bitset | aSet._bitset); + return result; + } + + AbstractRegSet operator-(const AbstractRegSet aSet) const { + AbstractRegSet result(_bitset & ~aSet._bitset); + return result; + } + + AbstractRegSet &operator+=(const AbstractRegSet aSet) { + *this = *this + aSet; + return *this; + } + + AbstractRegSet &operator-=(const AbstractRegSet aSet) { + *this = *this - aSet; + return *this; + } + + static AbstractRegSet of(RegImpl r1) { + return AbstractRegSet(r1); + } + + static AbstractRegSet of(RegImpl r1, RegImpl r2) { + return of(r1) + r2; + } + + static AbstractRegSet of(RegImpl r1, RegImpl r2, RegImpl r3) { + return of(r1, r2) + r3; + } + + static AbstractRegSet of(RegImpl r1, RegImpl r2, RegImpl r3, RegImpl r4) { + return of(r1, r2, r3) + r4; + } + + static AbstractRegSet range(RegImpl start, RegImpl end) { + assert(start <= end, "must be"); + uint32_t bits = ~0; + bits <<= start->encoding(); + bits <<= 31 - end->encoding(); + bits >>= 31 - end->encoding(); + + return AbstractRegSet(bits); + } + + uint size() const { return population_count(_bitset); } + + uint32_t bits() const { return _bitset; } + +private: + + RegImpl first(); + RegImpl last(); + +public: + + friend class RegSetIterator; + friend class ReverseRegSetIterator; + + RegSetIterator begin(); + ReverseRegSetIterator rbegin(); +}; + +template +class RegSetIterator { + AbstractRegSet _regs; + +public: + RegSetIterator(AbstractRegSet x): _regs(x) {} + RegSetIterator(const RegSetIterator& mit) : _regs(mit._regs) {} + + RegSetIterator& operator++() { + RegImpl r = _regs.first(); + if (r->is_valid()) + _regs -= r; + return *this; + } + + bool operator==(const RegSetIterator& rhs) const { + return _regs.bits() == rhs._regs.bits(); + } + bool operator!=(const RegSetIterator& rhs) const { + return ! (rhs == *this); + } + + RegImpl operator*() { + return _regs.first(); + } +}; + +template +inline RegSetIterator AbstractRegSet::begin() { + return RegSetIterator(*this); +} + +template +class ReverseRegSetIterator { + AbstractRegSet _regs; + +public: + ReverseRegSetIterator(AbstractRegSet x): _regs(x) {} + ReverseRegSetIterator(const ReverseRegSetIterator& mit) : _regs(mit._regs) {} + + ReverseRegSetIterator& operator++() { + RegImpl r = _regs.last(); + if (r->is_valid()) + _regs -= r; + return *this; + } + + bool operator==(const ReverseRegSetIterator& rhs) const { + return _regs.bits() == rhs._regs.bits(); + } + bool operator!=(const ReverseRegSetIterator& rhs) const { + return ! (rhs == *this); + } + + RegImpl operator*() { + return _regs.last(); + } +}; + +template +inline ReverseRegSetIterator AbstractRegSet::rbegin() { + return ReverseRegSetIterator(*this); +} #include CPU_HEADER(register) diff --git a/src/hotspot/share/c1/c1_Compilation.cpp b/src/hotspot/share/c1/c1_Compilation.cpp index 27c20a9c5fe4242132a7c5ccf9ccc2f58fa58886..baabbbd147bb82b696435f03fd50bcb114c03833 100644 --- a/src/hotspot/share/c1/c1_Compilation.cpp +++ b/src/hotspot/share/c1/c1_Compilation.cpp @@ -77,7 +77,6 @@ static int totalInstructionNodes = 0; class PhaseTraceTime: public TraceTime { private: - JavaThread* _thread; CompileLog* _log; TimerName _timer; @@ -560,6 +559,7 @@ Compilation::Compilation(AbstractCompiler* compiler, ciEnv* env, ciMethod* metho , _has_exception_handlers(false) , _has_fpu_code(true) // pessimistic assumption , _has_unsafe_access(false) +, _has_irreducible_loops(false) , _would_profile(false) , _has_method_handle_invokes(false) , _has_reserved_stack_access(method->has_reserved_stack_access()) diff --git a/src/hotspot/share/c1/c1_Compilation.hpp b/src/hotspot/share/c1/c1_Compilation.hpp index f3be9ed7cee295410cfbc521dd1a415f3e899757..02a2f367df37a5930c4efa3df1d1cf954843fc70 100644 --- a/src/hotspot/share/c1/c1_Compilation.hpp +++ b/src/hotspot/share/c1/c1_Compilation.hpp @@ -77,6 +77,7 @@ class Compilation: public StackObj { bool _has_exception_handlers; bool _has_fpu_code; bool _has_unsafe_access; + bool _has_irreducible_loops; bool _would_profile; bool _has_method_handle_invokes; // True if this method has MethodHandle invokes. bool _has_reserved_stack_access; @@ -135,6 +136,7 @@ class Compilation: public StackObj { bool has_exception_handlers() const { return _has_exception_handlers; } bool has_fpu_code() const { return _has_fpu_code; } bool has_unsafe_access() const { return _has_unsafe_access; } + bool has_irreducible_loops() const { return _has_irreducible_loops; } int max_vector_size() const { return 0; } ciMethod* method() const { return _method; } int osr_bci() const { return _osr_bci; } @@ -162,6 +164,7 @@ class Compilation: public StackObj { void set_has_exception_handlers(bool f) { _has_exception_handlers = f; } void set_has_fpu_code(bool f) { _has_fpu_code = f; } void set_has_unsafe_access(bool f) { _has_unsafe_access = f; } + void set_has_irreducible_loops(bool f) { _has_irreducible_loops = f; } void set_would_profile(bool f) { _would_profile = f; } void set_has_access_indexed(bool f) { _has_access_indexed = f; } // Add a set of exception handlers covering the given PC offset diff --git a/src/hotspot/share/c1/c1_GraphBuilder.cpp b/src/hotspot/share/c1/c1_GraphBuilder.cpp index 1b58188d422cd255d1be1a4a7af413986092444b..6bb39e38f6920bc8b3544ee407301ba634e8158c 100644 --- a/src/hotspot/share/c1/c1_GraphBuilder.cpp +++ b/src/hotspot/share/c1/c1_GraphBuilder.cpp @@ -59,7 +59,7 @@ class BlockListBuilder { // fields used by mark_loops ResourceBitMap _active; // for iteration of control flow graph ResourceBitMap _visited; // for iteration of control flow graph - intArray _loop_map; // caches the information if a block is contained in a loop + GrowableArray _loop_map; // caches the information if a block is contained in a loop int _next_loop_index; // next free loop number int _next_block_number; // for reverse postorder numbering of blocks @@ -84,7 +84,7 @@ class BlockListBuilder { void make_loop_header(BlockBegin* block); void mark_loops(); - int mark_loops(BlockBegin* b, bool in_subroutine); + BitMap& mark_loops(BlockBegin* b, bool in_subroutine); // debugging #ifndef PRODUCT @@ -376,17 +376,36 @@ void BlockListBuilder::mark_loops() { _active.initialize(BlockBegin::number_of_blocks()); _visited.initialize(BlockBegin::number_of_blocks()); - _loop_map = intArray(BlockBegin::number_of_blocks(), BlockBegin::number_of_blocks(), 0); + _loop_map = GrowableArray(BlockBegin::number_of_blocks(), BlockBegin::number_of_blocks(), ResourceBitMap()); + for (int i = 0; i < BlockBegin::number_of_blocks(); i++) { + _loop_map.at(i).initialize(BlockBegin::number_of_blocks()); + } _next_loop_index = 0; _next_block_number = _blocks.length(); - // recursively iterate the control flow graph - mark_loops(_bci2block->at(0), false); + // The loop detection algorithm works as follows: + // - We maintain the _loop_map, where for each block we have a bitmap indicating which loops contain this block. + // - The CFG is recursively traversed (depth-first) and if we detect a loop, we assign the loop a unique number that is stored + // in the bitmap associated with the loop header block. Until we return back through that loop header the bitmap contains + // only a single bit corresponding to the loop number. + // - The bit is then propagated for all the blocks in the loop after we exit them (post-order). There could be multiple bits + // of course in case of nested loops. + // - When we exit the loop header we remove that single bit and assign the real loop state for it. + // - Now, the tricky part here is how we detect irriducible loops. In the algorithm above the loop state bits + // are propagated to the predecessors. If we encounter an irreducible loop (a loop with multiple heads) we would see + // a node with some loop bit set that would then propagate back and be never cleared because we would + // never go back through the original loop header. Therefore if there are any irreducible loops the bits in the states + // for these loops are going to propagate back to the root. + BitMap& loop_state = mark_loops(_bci2block->at(0), false); + if (!loop_state.is_empty()) { + compilation()->set_has_irreducible_loops(true); + } assert(_next_block_number >= 0, "invalid block numbers"); // Remove dangling Resource pointers before the ResourceMark goes out-of-scope. _active.resize(0); _visited.resize(0); + _loop_map.clear(); } void BlockListBuilder::make_loop_header(BlockBegin* block) { @@ -398,19 +417,17 @@ void BlockListBuilder::make_loop_header(BlockBegin* block) { if (!block->is_set(BlockBegin::parser_loop_header_flag)) { block->set(BlockBegin::parser_loop_header_flag); - assert(_loop_map.at(block->block_id()) == 0, "must not be set yet"); - assert(0 <= _next_loop_index && _next_loop_index < BitsPerInt, "_next_loop_index is used as a bit-index in integer"); - _loop_map.at_put(block->block_id(), 1 << _next_loop_index); - if (_next_loop_index < 31) _next_loop_index++; + assert(_loop_map.at(block->block_id()).is_empty(), "must not be set yet"); + assert(0 <= _next_loop_index && _next_loop_index < BlockBegin::number_of_blocks(), "_next_loop_index is too large"); + _loop_map.at(block->block_id()).set_bit(_next_loop_index++); } else { // block already marked as loop header - assert(is_power_of_2((unsigned int)_loop_map.at(block->block_id())), "exactly one bit must be set"); + assert(_loop_map.at(block->block_id()).count_one_bits() == 1, "exactly one bit must be set"); } } -int BlockListBuilder::mark_loops(BlockBegin* block, bool in_subroutine) { +BitMap& BlockListBuilder::mark_loops(BlockBegin* block, bool in_subroutine) { int block_id = block->block_id(); - if (_visited.at(block_id)) { if (_active.at(block_id)) { // reached block via backward branch @@ -428,10 +445,11 @@ int BlockListBuilder::mark_loops(BlockBegin* block, bool in_subroutine) { _visited.set_bit(block_id); _active.set_bit(block_id); - intptr_t loop_state = 0; + ResourceMark rm; + ResourceBitMap loop_state(BlockBegin::number_of_blocks()); for (int i = number_of_successors(block) - 1; i >= 0; i--) { // recursively process all successors - loop_state |= mark_loops(successor_at(block, i), in_subroutine); + loop_state.set_union(mark_loops(successor_at(block, i), in_subroutine)); } // clear active-bit after all successors are processed @@ -441,26 +459,22 @@ int BlockListBuilder::mark_loops(BlockBegin* block, bool in_subroutine) { block->set_depth_first_number(_next_block_number); _next_block_number--; - if (loop_state != 0 || in_subroutine ) { + if (!loop_state.is_empty() || in_subroutine ) { // block is contained at least in one loop, so phi functions are necessary // phi functions are also necessary for all locals stored in a subroutine scope()->requires_phi_function().set_union(block->stores_to_locals()); } if (block->is_set(BlockBegin::parser_loop_header_flag)) { - int header_loop_state = _loop_map.at(block_id); - assert(is_power_of_2((unsigned)header_loop_state), "exactly one bit must be set"); - - // If the highest bit is set (i.e. when integer value is negative), the method - // has 32 or more loops. This bit is never cleared because it is used for multiple loops - if (header_loop_state >= 0) { - clear_bits(loop_state, header_loop_state); - } + BitMap& header_loop_state = _loop_map.at(block_id); + assert(header_loop_state.count_one_bits() == 1, "exactly one bit must be set"); + // remove the bit with the loop number for the state (header is outside of the loop) + loop_state.set_difference(header_loop_state); } // cache and return loop information for this block - _loop_map.at_put(block_id, loop_state); - return loop_state; + _loop_map.at(block_id).set_from(loop_state); + return _loop_map.at(block_id); } inline int BlockListBuilder::number_of_successors(BlockBegin* block) @@ -953,7 +967,8 @@ void GraphBuilder::load_constant() { } Value x; if (patch_state != NULL) { - x = new Constant(t, patch_state); + bool kills_memory = stream()->is_dynamic_constant(); // arbitrary memory effects from running BSM during linkage + x = new Constant(t, patch_state, kills_memory); } else { x = new Constant(t); } @@ -2495,7 +2510,7 @@ XHandlers* GraphBuilder::handle_exception(Instruction* instruction) { // The only test case we've seen so far which exhibits this // problem is caught by the infinite recursion test in // GraphBuilder::jsr() if the join doesn't work. - if (!entry->try_merge(cur_state)) { + if (!entry->try_merge(cur_state, compilation()->has_irreducible_loops())) { BAILOUT_("error while joining with exception handler, prob. due to complicated jsr/rets", exception_handlers); } @@ -2981,7 +2996,7 @@ BlockEnd* GraphBuilder::iterate_bytecodes_for_block(int bci) { BlockBegin* sux = end->sux_at(i); assert(sux->is_predecessor(block()), "predecessor missing"); // be careful, bailout if bytecodes are strange - if (!sux->try_merge(end->state())) BAILOUT_("block join failed", NULL); + if (!sux->try_merge(end->state(), compilation()->has_irreducible_loops())) BAILOUT_("block join failed", NULL); scope_data()->add_to_work_list(end->sux_at(i)); } @@ -3135,7 +3150,7 @@ BlockBegin* GraphBuilder::setup_start_block(int osr_bci, BlockBegin* std_entry, if (base->std_entry()->state() == NULL) { // setup states for header blocks - base->std_entry()->merge(state); + base->std_entry()->merge(state, compilation()->has_irreducible_loops()); } assert(base->std_entry()->state() != NULL, ""); @@ -3218,7 +3233,7 @@ void GraphBuilder::setup_osr_entry_block() { Goto* g = new Goto(target, false); append(g); _osr_entry->set_end(g); - target->merge(_osr_entry->end()->state()); + target->merge(_osr_entry->end()->state(), compilation()->has_irreducible_loops()); scope_data()->set_stream(NULL); } @@ -3277,7 +3292,7 @@ GraphBuilder::GraphBuilder(Compilation* compilation, IRScope* scope) // setup state for std entry _initial_state = state_at_entry(); - start_block->merge(_initial_state); + start_block->merge(_initial_state, compilation->has_irreducible_loops()); // End nulls still exist here @@ -4028,7 +4043,7 @@ bool GraphBuilder::try_inline_full(ciMethod* callee, bool holder_known, bool ign // the entry bci for the callee instead of the call site bci. append_with_bci(goto_callee, 0); _block->set_end(goto_callee); - callee_start_block->merge(callee_state); + callee_start_block->merge(callee_state, compilation()->has_irreducible_loops()); _last = _block = callee_start_block; diff --git a/src/hotspot/share/c1/c1_Instruction.cpp b/src/hotspot/share/c1/c1_Instruction.cpp index 4b66796a543f02cb6026b6d1d8d51d08a4b4d434..75cb0c2ccd65ed4e96175ea53335a4f418442f6e 100644 --- a/src/hotspot/share/c1/c1_Instruction.cpp +++ b/src/hotspot/share/c1/c1_Instruction.cpp @@ -719,7 +719,7 @@ void BlockBegin::block_values_do(ValueVisitor* f) { #endif -bool BlockBegin::try_merge(ValueStack* new_state) { +bool BlockBegin::try_merge(ValueStack* new_state, bool has_irreducible_loops) { TRACE_PHI(tty->print_cr("********** try_merge for block B%d", block_id())); // local variables used for state iteration @@ -760,10 +760,9 @@ bool BlockBegin::try_merge(ValueStack* new_state) { } BitMap& requires_phi_function = new_state->scope()->requires_phi_function(); - for_each_local_value(new_state, index, new_value) { bool requires_phi = requires_phi_function.at(index) || (new_value->type()->is_double_word() && requires_phi_function.at(index + 1)); - if (requires_phi || !SelectivePhiFunctions) { + if (requires_phi || !SelectivePhiFunctions || has_irreducible_loops) { new_state->setup_phi_for_local(this, index); TRACE_PHI(tty->print_cr("creating phi-function %c%d for local %d", new_state->local_at(index)->type()->tchar(), new_state->local_at(index)->id(), index)); } diff --git a/src/hotspot/share/c1/c1_Instruction.hpp b/src/hotspot/share/c1/c1_Instruction.hpp index 1646557018f75496702cafd80b1020cc16fb1995..10bc7eb4fdf09ec4027d366ad58326b5af11e847 100644 --- a/src/hotspot/share/c1/c1_Instruction.hpp +++ b/src/hotspot/share/c1/c1_Instruction.hpp @@ -363,6 +363,7 @@ class Instruction: public CompilationResourceObj { NeedsRangeCheckFlag, InWorkListFlag, DeoptimizeOnException, + KillsMemoryFlag, InstructionLastFlag }; @@ -718,13 +719,13 @@ LEAF(Constant, Instruction) assert(type->is_constant(), "must be a constant"); } - Constant(ValueType* type, ValueStack* state_before): + Constant(ValueType* type, ValueStack* state_before, bool kills_memory = false): Instruction(type, state_before, /*type_is_constant*/ true) { assert(state_before != NULL, "only used for constants which need patching"); assert(type->is_constant(), "must be a constant"); - // since it's patching it needs to be pinned - pin(); + set_flag(KillsMemoryFlag, kills_memory); + pin(); // since it's patching it needs to be pinned } // generic @@ -736,6 +737,8 @@ LEAF(Constant, Instruction) virtual ciType* exact_type() const; + bool kills_memory() const { return check_flag(KillsMemoryFlag); } + enum CompareResult { not_comparable = -1, cond_false, cond_true }; virtual CompareResult compare(Instruction::Condition condition, Value right) const; @@ -1776,8 +1779,11 @@ LEAF(BlockBegin, StateSplit) int loop_index() const { return _loop_index; } // merging - bool try_merge(ValueStack* state); // try to merge states at block begin - void merge(ValueStack* state) { bool b = try_merge(state); assert(b, "merge failed"); } + bool try_merge(ValueStack* state, bool has_irreducible_loops); // try to merge states at block begin + void merge(ValueStack* state, bool has_irreducible_loops) { + bool b = try_merge(state, has_irreducible_loops); + assert(b, "merge failed"); + } // debugging void print_block() PRODUCT_RETURN; diff --git a/src/hotspot/share/c1/c1_LIRAssembler.cpp b/src/hotspot/share/c1/c1_LIRAssembler.cpp index be0a6abc2ca22f1fec53838ec73a3a68b06d3056..1c4e0d09306b52906385e1f16b44be4399f8bd99 100644 --- a/src/hotspot/share/c1/c1_LIRAssembler.cpp +++ b/src/hotspot/share/c1/c1_LIRAssembler.cpp @@ -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 @@ -32,7 +32,6 @@ #include "c1/c1_ValueStack.hpp" #include "ci/ciInstance.hpp" #include "compiler/oopMap.hpp" -#include "gc/shared/barrierSet.hpp" #include "runtime/os.hpp" #include "runtime/vm_version.hpp" @@ -104,7 +103,6 @@ PatchingStub::PatchID LIR_Assembler::patching_id(CodeEmitInfo* info) { LIR_Assembler::LIR_Assembler(Compilation* c): _masm(c->masm()) - , _bs(BarrierSet::barrier_set()) , _compilation(c) , _frame_map(c->frame_map()) , _current_block(NULL) diff --git a/src/hotspot/share/c1/c1_LIRAssembler.hpp b/src/hotspot/share/c1/c1_LIRAssembler.hpp index f27ade60bae2869f06ae8a7d835a9f9ca8843ed1..1d873b9638da08d1493264b3620b006468b32e2f 100644 --- a/src/hotspot/share/c1/c1_LIRAssembler.hpp +++ b/src/hotspot/share/c1/c1_LIRAssembler.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 @@ -32,13 +32,11 @@ class Compilation; class ScopeValue; -class BarrierSet; class LIR_Assembler: public CompilationResourceObj { private: C1_MacroAssembler* _masm; CodeStubList* _slow_case_stubs; - BarrierSet* _bs; Compilation* _compilation; FrameMap* _frame_map; diff --git a/src/hotspot/share/c1/c1_ValueMap.hpp b/src/hotspot/share/c1/c1_ValueMap.hpp index 3ada748c67af3eb0808504c4d8b636c097ed843e..303ebba6c9d8a1bd5e0aec75ecc691fab9aa3d75 100644 --- a/src/hotspot/share/c1/c1_ValueMap.hpp +++ b/src/hotspot/share/c1/c1_ValueMap.hpp @@ -164,7 +164,12 @@ class ValueNumberingVisitor: public InstructionVisitor { void do_Phi (Phi* x) { /* nothing to do */ } void do_Local (Local* x) { /* nothing to do */ } - void do_Constant (Constant* x) { /* nothing to do */ } + void do_Constant (Constant* x) { + if (x->kills_memory()) { + assert(x->can_trap(), "already linked"); + kill_memory(); + } + } void do_LoadField (LoadField* x) { if (x->is_init_point() || // getstatic is an initialization point so treat it as a wide kill x->field()->is_volatile()) { // the JMM requires this diff --git a/src/hotspot/share/cds/archiveBuilder.cpp b/src/hotspot/share/cds/archiveBuilder.cpp index cb5c0aeb8c78008f044e0d009bddbd102fa38bbb..89529b2cf595de49207ec999afc316bdd68b2e3f 100644 --- a/src/hotspot/share/cds/archiveBuilder.cpp +++ b/src/hotspot/share/cds/archiveBuilder.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 @@ -522,7 +522,8 @@ ArchiveBuilder::FollowMode ArchiveBuilder::get_follow_mode(MetaspaceClosure::Ref if (MetaspaceShared::is_in_shared_metaspace(obj)) { // Don't dump existing shared metadata again. return point_to_it; - } else if (ref->msotype() == MetaspaceObj::MethodDataType) { + } else if (ref->msotype() == MetaspaceObj::MethodDataType || + ref->msotype() == MetaspaceObj::MethodCountersType) { return set_to_null; } else { if (ref->msotype() == MetaspaceObj::ClassType) { diff --git a/src/hotspot/share/cds/archiveUtils.hpp b/src/hotspot/share/cds/archiveUtils.hpp index 588ad1b6da921152f1caaf4827504286d2e969ba..be8d8a0e84ed5add863781a91217db12e9fce2ee 100644 --- a/src/hotspot/share/cds/archiveUtils.hpp +++ b/src/hotspot/share/cds/archiveUtils.hpp @@ -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 @@ -30,6 +30,7 @@ #include "memory/virtualspace.hpp" #include "utilities/bitMap.hpp" #include "utilities/exceptions.hpp" +#include "utilities/macros.hpp" class BootstrapInfo; class ReservedSpace; @@ -147,7 +148,7 @@ public: char* expand_top_to(char* newtop); char* allocate(size_t num_bytes); - void append_intptr_t(intptr_t n, bool need_to_mark = false); + void append_intptr_t(intptr_t n, bool need_to_mark = false) NOT_CDS_RETURN; char* base() const { return _base; } char* top() const { return _top; } diff --git a/src/hotspot/share/cds/cdsHeapVerifier.cpp b/src/hotspot/share/cds/cdsHeapVerifier.cpp new file mode 100644 index 0000000000000000000000000000000000000000..1eff911690110f9d8e0f1a59ab9f1fce92b82c9c --- /dev/null +++ b/src/hotspot/share/cds/cdsHeapVerifier.cpp @@ -0,0 +1,305 @@ +/* + * 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 "precompiled.hpp" +#include "cds/archiveBuilder.hpp" +#include "cds/cdsHeapVerifier.hpp" +#include "classfile/classLoaderDataGraph.hpp" +#include "classfile/javaClasses.inline.hpp" +#include "logging/log.hpp" +#include "logging/logStream.hpp" +#include "memory/resourceArea.hpp" +#include "oops/fieldStreams.inline.hpp" +#include "oops/klass.inline.hpp" +#include "oops/oop.inline.hpp" +#include "runtime/fieldDescriptor.inline.hpp" + +#if INCLUDE_CDS_JAVA_HEAP + +// CDSHeapVerifier is used to check for problems where an archived object references a +// static field that may be reinitialized at runtime. In the following example, +// Foo.get.test() +// correctly returns true when CDS disabled, but incorrectly returns false when CDS is enabled. +// +// class Foo { +// final Foo archivedFoo; // this field is archived by CDS +// Bar bar; +// static { +// CDS.initializeFromArchive(Foo.class); +// if (archivedFoo == null) { +// archivedFoo = new Foo(); +// archivedFoo.bar = Bar.bar; +// } +// } +// static Foo get() { return archivedFoo; } +// boolean test() { +// return bar == Bar.bar; +// } +// } +// +// class Bar { +// // this field is initialized in both CDS dump time and runtime. +// static final Bar bar = new Bar(); +// } +// +// The check itself is simple: +// [1] CDSHeapVerifier::do_klass() collects all static fields +// [2] CDSHeapVerifier::do_entry() checks all the archived objects. None of them +// should be in [1] +// +// However, it's legal for *some* static fields to be references. This leads to the +// table of ADD_EXCL below. +// +// [A] In most of the cases, the module bootstrap code will update the static field +// to point to part of the archived module graph. E.g., +// - java/lang/System::bootLayer +// - jdk/internal/loader/ClassLoaders::BOOT_LOADER +// [B] A final static String that's explicitly initialized inside , but +// its value is deterministic and is always the same string literal. +// [C] A non-final static string that is assigned a string literal during class +// initialization; this string is never changed during -Xshare:dump. +// [D] Simple caches whose value doesn't matter. +// [E] Other cases (see comments in-line below). + +CDSHeapVerifier::CDSHeapVerifier() : _archived_objs(0), _problems(0) +{ +# define ADD_EXCL(...) { static const char* e[] = {__VA_ARGS__, NULL}; add_exclusion(e); } + + // Unfortunately this needs to be manually maintained. If + // test/hotspot/jtreg/runtime/cds/appcds/cacheObject/ArchivedEnumTest.java fails, + // you might need to fix the core library code, or fix the ADD_EXCL entries below. + // + // class field type + ADD_EXCL("java/lang/ClassLoader", "scl"); // A + ADD_EXCL("java/lang/invoke/InvokerBytecodeGenerator", "DONTINLINE_SIG", // B + "FORCEINLINE_SIG", // B + "HIDDEN_SIG", // B + "INJECTEDPROFILE_SIG", // B + "LF_COMPILED_SIG"); // B + ADD_EXCL("java/lang/Module", "ALL_UNNAMED_MODULE", // A + "ALL_UNNAMED_MODULE_SET", // A + "EVERYONE_MODULE", // A + "EVERYONE_SET"); // A + ADD_EXCL("java/lang/System", "bootLayer"); // A + ADD_EXCL("java/lang/VersionProps", "VENDOR_URL_BUG", // C + "VENDOR_URL_VM_BUG", // C + "VENDOR_VERSION"); // C + ADD_EXCL("java/net/URL$DefaultFactory", "PREFIX"); // B FIXME: JDK-8276561 + + // A dummy object used by HashSet. The value doesn't matter and it's never + // tested for equality. + ADD_EXCL("java/util/HashSet", "PRESENT"); // E + ADD_EXCL("jdk/internal/loader/BuiltinClassLoader", "packageToModule"); // A + ADD_EXCL("jdk/internal/loader/ClassLoaders", "BOOT_LOADER", // A + "APP_LOADER", // A + "PLATFORM_LOADER"); // A + ADD_EXCL("jdk/internal/loader/URLClassPath", "JAVA_VERSION"); // B + ADD_EXCL("jdk/internal/module/Builder", "cachedVersion"); // D + ADD_EXCL("jdk/internal/module/ModuleLoaderMap$Mapper", "APP_CLASSLOADER", // A + "APP_LOADER_INDEX", // A + "PLATFORM_CLASSLOADER", // A + "PLATFORM_LOADER_INDEX"); // A + ADD_EXCL("jdk/internal/module/ServicesCatalog", "CLV"); // A + + // This just points to an empty Map + ADD_EXCL("jdk/internal/reflect/Reflection", "methodFilterMap"); // E + ADD_EXCL("jdk/internal/util/StaticProperty", "FILE_ENCODING"); // C + + // Integer for 0 and 1 are in java/lang/Integer$IntegerCache and are archived + ADD_EXCL("sun/invoke/util/ValueConversions", "ONE_INT", // E + "ZERO_INT"); // E + ADD_EXCL("sun/security/util/SecurityConstants", "PROVIDER_VER"); // C + + +# undef ADD_EXCL + + ClassLoaderDataGraph::classes_do(this); +} + +CDSHeapVerifier::~CDSHeapVerifier() { + if (_problems > 0) { + log_warning(cds, heap)("Scanned %d objects. Found %d case(s) where " + "an object points to a static field that may be " + "reinitialized at runtime.", _archived_objs, _problems); + } +} + +class CDSHeapVerifier::CheckStaticFields : public FieldClosure { + CDSHeapVerifier* _verifier; + InstanceKlass* _ik; + const char** _exclusions; +public: + CheckStaticFields(CDSHeapVerifier* verifier, InstanceKlass* ik) + : _verifier(verifier), _ik(ik) { + _exclusions = _verifier->find_exclusion(_ik); + } + + void do_field(fieldDescriptor* fd) { + if (fd->field_type() != T_OBJECT) { + return; + } + + oop static_obj_field = _ik->java_mirror()->obj_field(fd->offset()); + if (static_obj_field != NULL) { + Klass* klass = static_obj_field->klass(); + if (_exclusions != NULL) { + for (const char** p = _exclusions; *p != NULL; p++) { + if (fd->name()->equals(*p)) { + return; + } + } + } + + if (fd->is_final() && java_lang_String::is_instance(static_obj_field) && fd->has_initial_value()) { + // This field looks like like this in the Java source: + // static final SOME_STRING = "a string literal"; + // This string literal has been stored in the shared string table, so it's OK + // for the archived objects to refer to it. + return; + } + if (fd->is_final() && java_lang_Class::is_instance(static_obj_field)) { + // This field points to an archived mirror. + return; + } + if (klass->has_archived_enum_objs()) { + // This klass is a subclass of java.lang.Enum. If any instance of this klass + // has been archived, we will archive all static fields of this klass. + // See HeapShared::initialize_enum_klass(). + return; + } + + // This field *may* be initialized to a different value at runtime. Remember it + // and check later if it appears in the archived object graph. + _verifier->add_static_obj_field(_ik, static_obj_field, fd->name()); + } + } +}; + +// Remember all the static object fields of every class that are currently +// loaded. +void CDSHeapVerifier::do_klass(Klass* k) { + if (k->is_instance_klass()) { + InstanceKlass* ik = InstanceKlass::cast(k); + + if (HeapShared::is_subgraph_root_class(ik)) { + // ik is inside one of the ArchivableStaticFieldInfo tables + // in heapShared.cpp. We assume such classes are programmed to + // update their static fields correctly at runtime. + return; + } + + CheckStaticFields csf(this, ik); + ik->do_local_static_fields(&csf); + } +} + +void CDSHeapVerifier::add_static_obj_field(InstanceKlass* ik, oop field, Symbol* name) { + StaticFieldInfo info = {ik, name}; + _table.put(field, info); +} + +inline bool CDSHeapVerifier::do_entry(oop& orig_obj, HeapShared::CachedOopInfo& value) { + _archived_objs++; + + StaticFieldInfo* info = _table.get(orig_obj); + if (info != NULL) { + ResourceMark rm; + LogStream ls(Log(cds, heap)::warning()); + ls.print_cr("Archive heap points to a static field that may be reinitialized at runtime:"); + ls.print_cr("Field: %s::%s", info->_holder->name()->as_C_string(), info->_name->as_C_string()); + ls.print("Value: "); + orig_obj->print_on(&ls); + ls.print_cr("--- trace begin ---"); + trace_to_root(orig_obj, NULL, &value); + ls.print_cr("--- trace end ---"); + ls.cr(); + _problems ++; + } + + return true; /* keep on iterating */ +} + +class CDSHeapVerifier::TraceFields : public FieldClosure { + oop _orig_obj; + oop _orig_field; + LogStream* _ls; + +public: + TraceFields(oop orig_obj, oop orig_field, LogStream* ls) + : _orig_obj(orig_obj), _orig_field(orig_field), _ls(ls) {} + + 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()); + } + } + } +}; + +// 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) { + int level = 0; + LogStream ls(Log(cds, heap)::warning()); + if (p->_referrer != NULL) { + HeapShared::CachedOopInfo* ref = HeapShared::archived_object_cache()->get(p->_referrer); + assert(ref != NULL, "sanity"); + level = trace_to_root(p->_referrer, orig_obj, ref) + 1; + } else if (java_lang_String::is_instance(orig_obj)) { + ls.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()); + if (orig_field != NULL) { + if (k->is_instance_klass()) { + TraceFields clo(orig_obj, orig_field, &ls);; + 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); + break; + } + } + } + } + ls.cr(); + + return level; +} + +#ifdef ASSERT +void CDSHeapVerifier::verify() { + CDSHeapVerifier verf; + HeapShared::archived_object_cache()->iterate(&verf); +} +#endif + +#endif // INCLUDE_CDS_JAVA_HEAP diff --git a/src/hotspot/share/cds/cdsHeapVerifier.hpp b/src/hotspot/share/cds/cdsHeapVerifier.hpp new file mode 100644 index 0000000000000000000000000000000000000000..830e41ae03db77b1e1d4472c778b7125801308d3 --- /dev/null +++ b/src/hotspot/share/cds/cdsHeapVerifier.hpp @@ -0,0 +1,89 @@ +/* + * 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 SHARED_CDS_CDSHEAPVERIFIER_HPP +#define SHARED_CDS_CDSHEAPVERIFIER_HPP + +#include "cds/heapShared.hpp" +#include "memory/iterator.hpp" +#include "utilities/growableArray.hpp" +#include "utilities/resourceHash.hpp" + +class InstanceKlass; +class Symbol; + +#if INCLUDE_CDS_JAVA_HEAP + +class CDSHeapVerifier : public KlassClosure { + class CheckStaticFields; + class TraceFields; + + int _archived_objs; + int _problems; + + struct StaticFieldInfo { + InstanceKlass* _holder; + Symbol* _name; + }; + + ResourceHashtable _table; + + GrowableArray _exclusions; + + void add_exclusion(const char** excl) { + _exclusions.append(excl); + } + void add_static_obj_field(InstanceKlass* ik, oop field, Symbol* name); + + const char** find_exclusion(InstanceKlass* ik) { + for (int i = 0; i < _exclusions.length(); i++) { + const char** excl = _exclusions.at(i); + if (ik->name()->equals(excl[0])) { + return &excl[1]; + } + } + return NULL; + } + int trace_to_root(oop orig_obj, oop orig_field, HeapShared::CachedOopInfo* p); + + CDSHeapVerifier(); + ~CDSHeapVerifier(); + +public: + + // Overrides KlassClosure::do_klass() + virtual void do_klass(Klass* k); + + // For ResourceHashtable::iterate() + inline bool do_entry(oop& orig_obj, HeapShared::CachedOopInfo& value); + + static void verify() NOT_DEBUG_RETURN; +}; + +#endif // INCLUDE_CDS_JAVA_HEAP +#endif // SHARED_CDS_CDSHEAPVERIFIER_HPP diff --git a/src/hotspot/share/cds/dumpTimeClassInfo.cpp b/src/hotspot/share/cds/dumpTimeClassInfo.cpp index 77225969b1a4db35d5d9753aa6cff31cf9be1353..ac35e6583b4c4cfb2295b3c9fa7066f17dfe6d20 100644 --- a/src/hotspot/share/cds/dumpTimeClassInfo.cpp +++ b/src/hotspot/share/cds/dumpTimeClassInfo.cpp @@ -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 @@ -25,6 +25,7 @@ #include "precompiled.hpp" #include "cds/archiveBuilder.hpp" #include "cds/dumpTimeClassInfo.inline.hpp" +#include "cds/runTimeClassInfo.hpp" #include "classfile/classLoader.hpp" #include "classfile/classLoaderData.inline.hpp" #include "classfile/systemDictionaryShared.hpp" @@ -45,6 +46,7 @@ DumpTimeClassInfo DumpTimeClassInfo::clone() { clone._verifier_constraints = NULL; clone._verifier_constraint_flags = NULL; clone._loader_constraints = NULL; + clone._enum_klass_static_fields = NULL; int clone_num_verifier_constraints = num_verifier_constraints(); if (clone_num_verifier_constraints > 0) { clone._verifier_constraints = new (ResourceObj::C_HEAP, mtClass) GrowableArray(clone_num_verifier_constraints, mtClass); @@ -61,9 +63,16 @@ DumpTimeClassInfo DumpTimeClassInfo::clone() { clone._loader_constraints->append(_loader_constraints->at(i)); } } + assert(_enum_klass_static_fields == NULL, "This should not happen with jcmd VM.cds dumping"); return clone; } +size_t DumpTimeClassInfo::runtime_info_bytesize() const { + return RunTimeClassInfo::byte_size(_klass, num_verifier_constraints(), + num_loader_constraints(), + num_enum_klass_static_fields()); +} + void DumpTimeClassInfo::add_verification_constraint(InstanceKlass* k, Symbol* name, Symbol* from_name, bool from_field_is_protected, bool from_is_array, bool from_is_object) { if (_verifier_constraints == NULL) { @@ -144,6 +153,18 @@ void DumpTimeClassInfo::record_linking_constraint(Symbol* name, Handle loader1, } } +void DumpTimeClassInfo::add_enum_klass_static_field(int archived_heap_root_index) { + if (_enum_klass_static_fields == NULL) { + _enum_klass_static_fields = new (ResourceObj::C_HEAP, mtClass) GrowableArray(20, mtClass); + } + _enum_klass_static_fields->append(archived_heap_root_index); +} + +int DumpTimeClassInfo::enum_klass_static_field(int which_field) { + assert(_enum_klass_static_fields != NULL, "must be"); + return _enum_klass_static_fields->at(which_field); +} + bool DumpTimeClassInfo::is_builtin() { return SystemDictionaryShared::is_builtin(_klass); } diff --git a/src/hotspot/share/cds/dumpTimeClassInfo.hpp b/src/hotspot/share/cds/dumpTimeClassInfo.hpp index 28fe986ff7a32c72a664f044bfd23ed658c47f44..5b4f5cd9b9beb1f494c5a2a68b8fba2aae757657 100644 --- a/src/hotspot/share/cds/dumpTimeClassInfo.hpp +++ b/src/hotspot/share/cds/dumpTimeClassInfo.hpp @@ -77,6 +77,7 @@ public: GrowableArray* _verifier_constraints; GrowableArray* _verifier_constraint_flags; GrowableArray* _loader_constraints; + GrowableArray* _enum_klass_static_fields; DumpTimeClassInfo() { _klass = NULL; @@ -92,28 +93,38 @@ public: _verifier_constraints = NULL; _verifier_constraint_flags = NULL; _loader_constraints = NULL; + _enum_klass_static_fields = NULL; } void add_verification_constraint(InstanceKlass* k, Symbol* name, Symbol* from_name, bool from_field_is_protected, bool from_is_array, bool from_is_object); void record_linking_constraint(Symbol* name, Handle loader1, Handle loader2); - + void add_enum_klass_static_field(int archived_heap_root_index); + int enum_klass_static_field(int which_field); bool is_builtin(); - int num_verifier_constraints() { - if (_verifier_constraint_flags != NULL) { - return _verifier_constraint_flags->length(); - } else { +private: + template + static int array_length_or_zero(GrowableArray* array) { + if (array == NULL) { return 0; + } else { + return array->length(); } } - int num_loader_constraints() { - if (_loader_constraints != NULL) { - return _loader_constraints->length(); - } else { - return 0; - } +public: + + int num_verifier_constraints() const { + return array_length_or_zero(_verifier_constraint_flags); + } + + int num_loader_constraints() const { + return array_length_or_zero(_loader_constraints); + } + + int num_enum_klass_static_fields() const { + return array_length_or_zero(_enum_klass_static_fields); } void metaspace_pointers_do(MetaspaceClosure* it) { @@ -151,11 +162,13 @@ public: void set_failed_verification() { _failed_verification = true; } InstanceKlass* nest_host() const { return _nest_host; } void set_nest_host(InstanceKlass* nest_host) { _nest_host = nest_host; } + DumpTimeClassInfo clone(); + size_t runtime_info_bytesize() const; }; - -inline unsigned DumpTimeSharedClassTable_hash(InstanceKlass* const& k) { +template +inline unsigned DumpTimeSharedClassTable_hash(T* const& k) { if (DumpSharedSpaces) { // Deterministic archive contents uintx delta = k->name() - MetaspaceShared::symbol_rs_base(); @@ -163,7 +176,7 @@ inline unsigned DumpTimeSharedClassTable_hash(InstanceKlass* const& k) { } else { // Deterministic archive is not possible because classes can be loaded // in multiple threads. - return primitive_hash(k); + return primitive_hash(k); } } diff --git a/src/hotspot/share/cds/filemap.cpp b/src/hotspot/share/cds/filemap.cpp index 69ab7430e16d881181ce530c2466ecbfabfe7982..b8e28f30b72bf21aa8c25194fa887da73e99194f 100644 --- a/src/hotspot/share/cds/filemap.cpp +++ b/src/hotspot/share/cds/filemap.cpp @@ -1108,6 +1108,9 @@ public: } ~FileHeaderHelper() { + if (_header != nullptr) { + FREE_C_HEAP_ARRAY(char, _header); + } if (_fd != -1) { ::close(_fd); } @@ -1994,7 +1997,7 @@ void FileMapInfo::map_or_load_heap_regions() { } else if (HeapShared::can_load()) { success = HeapShared::load_heap_regions(this); } else { - log_info(cds)("Cannot use CDS heap data. UseEpsilonGC, UseG1GC or UseSerialGC are required."); + log_info(cds)("Cannot use CDS heap data. UseEpsilonGC, UseG1GC, UseSerialGC or UseParallelGC are required."); } } diff --git a/src/hotspot/share/cds/heapShared.cpp b/src/hotspot/share/cds/heapShared.cpp index 922eab124af2baef29ff52e0a3eefb6df9912d23..14bca5d74b62bce1074da9f76694faaa04a7bfb2 100644 --- a/src/hotspot/share/cds/heapShared.cpp +++ b/src/hotspot/share/cds/heapShared.cpp @@ -25,6 +25,7 @@ #include "precompiled.hpp" #include "cds/archiveBuilder.hpp" #include "cds/archiveUtils.hpp" +#include "cds/cdsHeapVerifier.hpp" #include "cds/filemap.hpp" #include "cds/heapShared.inline.hpp" #include "cds/metaspaceShared.hpp" @@ -42,7 +43,6 @@ #include "gc/shared/gcLocker.hpp" #include "gc/shared/gcVMOperations.hpp" #include "logging/log.hpp" -#include "logging/logMessage.hpp" #include "logging/logStream.hpp" #include "memory/iterator.inline.hpp" #include "memory/metadataFactory.hpp" @@ -143,11 +143,24 @@ bool HeapShared::is_archived_object_during_dumptime(oop p) { } #endif -//////////////////////////////////////////////////////////////// -// -// Java heap object archiving support -// -//////////////////////////////////////////////////////////////// +static bool is_subgraph_root_class_of(ArchivableStaticFieldInfo fields[], int num, InstanceKlass* ik) { + for (int i = 0; i < num; i++) { + if (fields[i].klass == ik) { + return true; + } + } + return false; +} + +bool HeapShared::is_subgraph_root_class(InstanceKlass* ik) { + return is_subgraph_root_class_of(closed_archive_subgraph_entry_fields, + num_closed_archive_subgraph_entry_fields, ik) || + is_subgraph_root_class_of(open_archive_subgraph_entry_fields, + num_open_archive_subgraph_entry_fields, ik) || + is_subgraph_root_class_of(fmg_open_archive_subgraph_entry_fields, + num_fmg_open_archive_subgraph_entry_fields, ik); +} + void HeapShared::fixup_regions() { FileMapInfo* mapinfo = FileMapInfo::current_info(); if (is_mapped()) { @@ -203,9 +216,9 @@ HeapShared::ArchivedObjectCache* HeapShared::_archived_object_cache = NULL; oop HeapShared::find_archived_heap_object(oop obj) { assert(DumpSharedSpaces, "dump-time only"); ArchivedObjectCache* cache = archived_object_cache(); - oop* p = cache->get(obj); + CachedOopInfo* p = cache->get(obj); if (p != NULL) { - return *p; + return p->_obj; } else { return NULL; } @@ -302,7 +315,8 @@ oop HeapShared::archive_object(oop obj) { assert(hash_original == hash_archived, "Different hash codes: original %x, archived %x", hash_original, hash_archived); ArchivedObjectCache* cache = archived_object_cache(); - cache->put(obj, archived_oop); + CachedOopInfo info = make_cached_oop_info(archived_oop); + cache->put(obj, info); if (log_is_enabled(Debug, cds, heap)) { ResourceMark rm; log_debug(cds, heap)("Archived heap object " PTR_FORMAT " ==> " PTR_FORMAT " : %s", @@ -336,6 +350,94 @@ void HeapShared::archive_klass_objects() { } } +// -- Handling of Enum objects +// Java Enum classes have synthetic methods that look like this +// enum MyEnum {FOO, BAR} +// MyEnum:: { +// /*static final MyEnum*/ MyEnum::FOO = new MyEnum("FOO"); +// /*static final MyEnum*/ MyEnum::BAR = new MyEnum("BAR"); +// } +// +// If MyEnum::FOO object is referenced by any of the archived subgraphs, we must +// ensure the archived value equals (in object address) to the runtime value of +// MyEnum::FOO. +// +// However, since MyEnum:: is synthetically generated by javac, there's +// no way of programatically handling this inside the Java code (as you would handle +// ModuleLayer::EMPTY_LAYER, for example). +// +// Instead, we archive all static field of such Enum classes. At runtime, +// HeapShared::initialize_enum_klass() will skip the method and pull +// the static fields out of the archived heap. +void HeapShared::check_enum_obj(int level, + KlassSubGraphInfo* subgraph_info, + oop orig_obj, + bool is_closed_archive) { + Klass* k = orig_obj->klass(); + Klass* relocated_k = ArchiveBuilder::get_relocated_klass(k); + if (!k->is_instance_klass()) { + return; + } + InstanceKlass* ik = InstanceKlass::cast(k); + if (ik->java_super() == vmClasses::Enum_klass() && !ik->has_archived_enum_objs()) { + ResourceMark rm; + ik->set_has_archived_enum_objs(); + relocated_k->set_has_archived_enum_objs(); + oop mirror = ik->java_mirror(); + + for (JavaFieldStream fs(ik); !fs.done(); fs.next()) { + if (fs.access_flags().is_static()) { + fieldDescriptor& fd = fs.field_descriptor(); + if (fd.field_type() != T_OBJECT && fd.field_type() != T_ARRAY) { + guarantee(false, "static field %s::%s must be T_OBJECT or T_ARRAY", + ik->external_name(), fd.name()->as_C_string()); + } + oop oop_field = mirror->obj_field(fd.offset()); + if (oop_field == NULL) { + guarantee(false, "static field %s::%s must not be null", + ik->external_name(), fd.name()->as_C_string()); + } else if (oop_field->klass() != ik && oop_field->klass() != ik->array_klass_or_null()) { + guarantee(false, "static field %s::%s is of the wrong type", + ik->external_name(), fd.name()->as_C_string()); + } + oop archived_oop_field = archive_reachable_objects_from(level, subgraph_info, oop_field, is_closed_archive); + int root_index = append_root(archived_oop_field); + log_info(cds, heap)("Archived enum obj @%d %s::%s (" INTPTR_FORMAT " -> " INTPTR_FORMAT ")", + root_index, ik->external_name(), fd.name()->as_C_string(), + p2i((oopDesc*)oop_field), p2i((oopDesc*)archived_oop_field)); + SystemDictionaryShared::add_enum_klass_static_field(ik, root_index); + } + } + } +} + +// See comments in HeapShared::check_enum_obj() +bool HeapShared::initialize_enum_klass(InstanceKlass* k, TRAPS) { + if (!is_fully_available()) { + return false; + } + + RunTimeClassInfo* info = RunTimeClassInfo::get_for(k); + assert(info != NULL, "sanity"); + + if (log_is_enabled(Info, cds, heap)) { + ResourceMark rm; + log_info(cds, heap)("Initializing Enum class: %s", k->external_name()); + } + + oop mirror = k->java_mirror(); + int i = 0; + for (JavaFieldStream fs(k); !fs.done(); fs.next()) { + if (fs.access_flags().is_static()) { + int root_index = info->enum_klass_static_field_root_index_at(i++); + fieldDescriptor& fd = fs.field_descriptor(); + assert(fd.field_type() == T_OBJECT || fd.field_type() == T_ARRAY, "must be"); + mirror->obj_field_put(fd.offset(), get_root(root_index, /*clear=*/true)); + } + } + return true; +} + void HeapShared::run_full_gc_in_vm_thread() { if (HeapShared::can_write()) { // Avoid fragmentation while archiving heap objects. @@ -377,6 +479,7 @@ void HeapShared::archive_objects(GrowableArray* closed_regions, log_info(cds)("Dumping objects to open archive heap region ..."); copy_open_objects(open_regions); + CDSHeapVerifier::verify(); destroy_archived_object_cache(); } @@ -471,7 +574,7 @@ KlassSubGraphInfo* HeapShared::init_subgraph_info(Klass* k, bool is_full_module_ bool created; Klass* relocated_k = ArchiveBuilder::get_relocated_klass(k); KlassSubGraphInfo* info = - _dump_time_subgraph_info_table->put_if_absent(relocated_k, KlassSubGraphInfo(relocated_k, is_full_module_graph), + _dump_time_subgraph_info_table->put_if_absent(k, KlassSubGraphInfo(relocated_k, is_full_module_graph), &created); assert(created, "must not initialize twice"); return info; @@ -479,8 +582,7 @@ KlassSubGraphInfo* HeapShared::init_subgraph_info(Klass* k, bool is_full_module_ KlassSubGraphInfo* HeapShared::get_subgraph_info(Klass* k) { assert(DumpSharedSpaces, "dump time only"); - Klass* relocated_k = ArchiveBuilder::get_relocated_klass(k); - KlassSubGraphInfo* info = _dump_time_subgraph_info_table->get(relocated_k); + KlassSubGraphInfo* info = _dump_time_subgraph_info_table->get(k); assert(info != NULL, "must have been initialized"); return info; } @@ -641,7 +743,8 @@ struct CopyKlassSubGraphInfoToArchive : StackObj { (ArchivedKlassSubGraphInfoRecord*)ArchiveBuilder::ro_region_alloc(sizeof(ArchivedKlassSubGraphInfoRecord)); record->init(&info); - unsigned int hash = SystemDictionaryShared::hash_for_shared_dictionary((address)klass); + Klass* relocated_k = ArchiveBuilder::get_relocated_klass(klass); + unsigned int hash = SystemDictionaryShared::hash_for_shared_dictionary((address)relocated_k); u4 delta = ArchiveBuilder::current()->any_to_offset_u4(record); _writer->add(hash, delta); } @@ -903,6 +1006,11 @@ class WalkOopAndArchiveClosure: public BasicOopIterateClosure { KlassSubGraphInfo* _subgraph_info; oop _orig_referencing_obj; oop _archived_referencing_obj; + + // The following are for maintaining a stack for determining + // CachedOopInfo::_referrer + static WalkOopAndArchiveClosure* _current; + WalkOopAndArchiveClosure* _last; public: WalkOopAndArchiveClosure(int level, bool is_closed_archive, @@ -912,7 +1020,13 @@ class WalkOopAndArchiveClosure: public BasicOopIterateClosure { _level(level), _is_closed_archive(is_closed_archive), _record_klasses_only(record_klasses_only), _subgraph_info(subgraph_info), - _orig_referencing_obj(orig), _archived_referencing_obj(archived) {} + _orig_referencing_obj(orig), _archived_referencing_obj(archived) { + _last = _current; + _current = this; + } + ~WalkOopAndArchiveClosure() { + _current = _last; + } void do_oop(narrowOop *p) { WalkOopAndArchiveClosure::do_oop_work(p); } void do_oop( oop *p) { WalkOopAndArchiveClosure::do_oop_work(p); } @@ -949,8 +1063,26 @@ class WalkOopAndArchiveClosure: public BasicOopIterateClosure { } } } + + public: + static WalkOopAndArchiveClosure* current() { return _current; } + oop orig_referencing_obj() { return _orig_referencing_obj; } + KlassSubGraphInfo* subgraph_info() { return _subgraph_info; } }; +WalkOopAndArchiveClosure* WalkOopAndArchiveClosure::_current = NULL; + +HeapShared::CachedOopInfo HeapShared::make_cached_oop_info(oop orig_obj) { + CachedOopInfo info; + WalkOopAndArchiveClosure* walker = WalkOopAndArchiveClosure::current(); + + info._subgraph_info = (walker == NULL) ? NULL : walker->subgraph_info(); + info._referrer = (walker == NULL) ? NULL : walker->orig_referencing_obj(); + info._obj = orig_obj; + + return info; +} + void HeapShared::check_closed_region_object(InstanceKlass* k) { // Check fields in the object for (JavaFieldStream fs(k); !fs.done(); fs.next()) { @@ -1076,6 +1208,8 @@ oop HeapShared::archive_reachable_objects_from(int level, if (is_closed_archive && orig_k->is_instance_klass()) { check_closed_region_object(InstanceKlass::cast(orig_k)); } + + check_enum_obj(level + 1, subgraph_info, orig_obj, is_closed_archive); return archived_obj; } diff --git a/src/hotspot/share/cds/heapShared.hpp b/src/hotspot/share/cds/heapShared.hpp index fc7a0bcb57aec7972eea2b568b63b31cef982d3c..d8fc71fc76e9ba1279401c392363a6cb8f7fcfc4 100644 --- a/src/hotspot/share/cds/heapShared.hpp +++ b/src/hotspot/share/cds/heapShared.hpp @@ -25,6 +25,7 @@ #ifndef SHARE_CDS_HEAPSHARED_HPP #define SHARE_CDS_HEAPSHARED_HPP +#include "cds/dumpTimeClassInfo.hpp" #include "cds/metaspaceShared.hpp" #include "classfile/compactHashtable.hpp" #include "classfile/javaClasses.hpp" @@ -43,6 +44,7 @@ #if INCLUDE_CDS_JAVA_HEAP class DumpedInternedStrings; class FileMapInfo; +class KlassSubGraphInfo; struct ArchivableStaticFieldInfo { const char* klass_name; @@ -193,7 +195,7 @@ public: static bool is_fully_available() { return is_loaded() || is_mapped(); } - + static bool is_subgraph_root_class(InstanceKlass* ik); private: #if INCLUDE_CDS_JAVA_HEAP static bool _disable_writing; @@ -228,29 +230,35 @@ public: assert(is_in_loaded_heap(o), "must be"); } + struct CachedOopInfo { + KlassSubGraphInfo* _subgraph_info; + oop _referrer; + oop _obj; + CachedOopInfo() :_subgraph_info(), _referrer(), _obj() {} + }; + private: + static void check_enum_obj(int level, + KlassSubGraphInfo* subgraph_info, + oop orig_obj, + bool is_closed_archive); static bool is_in_loaded_heap(uintptr_t o) { return (_loaded_heap_bottom <= o && o < _loaded_heap_top); } - typedef ResourceHashtable ArchivedObjectCache; static ArchivedObjectCache* _archived_object_cache; - static unsigned klass_hash(Klass* const& klass) { - // Generate deterministic hashcode even if SharedBaseAddress is changed due to ASLR. - return primitive_hash
    (address(klass) - SharedBaseAddress); - } - class DumpTimeKlassSubGraphInfoTable : public ResourceHashtable { + DumpTimeSharedClassTable_hash> { public: int _count; }; @@ -272,7 +280,7 @@ private: static RunTimeKlassSubGraphInfoTable _run_time_subgraph_info_table; static void check_closed_region_object(InstanceKlass* k); - + static CachedOopInfo make_cached_oop_info(oop orig_obj); static void archive_object_subgraphs(ArchivableStaticFieldInfo fields[], int num, bool is_closed_archive, @@ -482,6 +490,7 @@ private: static void init_for_dumping(TRAPS) NOT_CDS_JAVA_HEAP_RETURN; static void write_subgraph_info_table() NOT_CDS_JAVA_HEAP_RETURN; static void serialize(SerializeClosure* soc) NOT_CDS_JAVA_HEAP_RETURN; + static bool initialize_enum_klass(InstanceKlass* k, TRAPS) NOT_CDS_JAVA_HEAP_RETURN_(false); }; #if INCLUDE_CDS_JAVA_HEAP diff --git a/src/hotspot/share/cds/runTimeClassInfo.cpp b/src/hotspot/share/cds/runTimeClassInfo.cpp index 52fa94c119d9c12a05ccd9f02e9b577f6845d157..77ec5de8c3b1e4df55e79a52cabbe1329239b932 100644 --- a/src/hotspot/share/cds/runTimeClassInfo.cpp +++ b/src/hotspot/share/cds/runTimeClassInfo.cpp @@ -1,6 +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 @@ -64,6 +63,15 @@ void RunTimeClassInfo::init(DumpTimeClassInfo& info) { InstanceKlass* n_h = info.nest_host(); set_nest_host(n_h); } + if (_klass->has_archived_enum_objs()) { + int num = info.num_enum_klass_static_fields(); + set_num_enum_klass_static_fields(num); + for (int i = 0; i < num; i++) { + int root_index = info.enum_klass_static_field(i); + set_enum_klass_static_field_root_index_at(i, root_index); + } + } + ArchivePtrMarker::mark_pointer(&_klass); } diff --git a/src/hotspot/share/cds/runTimeClassInfo.hpp b/src/hotspot/share/cds/runTimeClassInfo.hpp index adc828c4f88c28a9b3962913ef6e6d4d91a85713..74fdf92ebafa9ae70432bca1c8d656bb52299c8a 100644 --- a/src/hotspot/share/cds/runTimeClassInfo.hpp +++ b/src/hotspot/share/cds/runTimeClassInfo.hpp @@ -1,6 +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 @@ -64,30 +63,40 @@ public: return (Symbol*)(SharedBaseAddress + _name); } }; + struct RTEnumKlassStaticFields { + int _num; + int _root_indices[1]; + }; InstanceKlass* _klass; int _num_verifier_constraints; int _num_loader_constraints; - // optional CrcInfo _crc; (only for UNREGISTERED classes) - // optional InstanceKlass* _nest_host - // optional RTLoaderConstraint _loader_constraint_types[_num_loader_constraints] - // optional RTVerifierConstraint _verifier_constraints[_num_verifier_constraints] - // optional char _verifier_constraint_flags[_num_verifier_constraints] + // optional CrcInfo _crc; (only for UNREGISTERED classes) + // optional InstanceKlass* _nest_host + // optional RTLoaderConstraint _loader_constraint_types[_num_loader_constraints] + // optional RTVerifierConstraint _verifier_constraints[_num_verifier_constraints] + // optional char _verifier_constraint_flags[_num_verifier_constraints] + // optional RTEnumKlassStaticFields _enum_klass_static_fields; private: static size_t header_size_size() { - return sizeof(RunTimeClassInfo); + return align_up(sizeof(RunTimeClassInfo), wordSize); } static size_t verifier_constraints_size(int num_verifier_constraints) { - return sizeof(RTVerifierConstraint) * num_verifier_constraints; + return align_up(sizeof(RTVerifierConstraint) * num_verifier_constraints, wordSize); } static size_t verifier_constraint_flags_size(int num_verifier_constraints) { - return sizeof(char) * num_verifier_constraints; + return align_up(sizeof(char) * num_verifier_constraints, wordSize); } static size_t loader_constraints_size(int num_loader_constraints) { - return sizeof(RTLoaderConstraint) * num_loader_constraints; + return align_up(sizeof(RTLoaderConstraint) * num_loader_constraints, wordSize); } + static size_t enum_klass_static_fields_size(int num_fields) { + size_t size = num_fields <= 0 ? 0 : sizeof(RTEnumKlassStaticFields) + (num_fields - 1) * sizeof(int); + return align_up(size, wordSize); + } + static size_t nest_host_size(InstanceKlass* klass) { if (klass->is_hidden()) { return sizeof(InstanceKlass*); @@ -98,13 +107,15 @@ private: static size_t crc_size(InstanceKlass* klass); public: - static size_t byte_size(InstanceKlass* klass, int num_verifier_constraints, int num_loader_constraints) { + static size_t byte_size(InstanceKlass* klass, int num_verifier_constraints, int num_loader_constraints, + int num_enum_klass_static_fields) { return header_size_size() + crc_size(klass) + nest_host_size(klass) + loader_constraints_size(num_loader_constraints) + verifier_constraints_size(num_verifier_constraints) + - verifier_constraint_flags_size(num_verifier_constraints); + verifier_constraint_flags_size(num_verifier_constraints) + + enum_klass_static_fields_size(num_enum_klass_static_fields); } private: @@ -113,7 +124,7 @@ private: } size_t nest_host_offset() const { - return crc_offset() + crc_size(_klass); + return crc_offset() + crc_size(_klass); } size_t loader_constraints_offset() const { @@ -125,6 +136,9 @@ private: size_t verifier_constraint_flags_offset() const { return verifier_constraints_offset() + verifier_constraints_size(_num_verifier_constraints); } + size_t enum_klass_static_fields_offset() const { + return verifier_constraint_flags_offset() + verifier_constraint_flags_size(_num_verifier_constraints); + } void check_verifier_constraint_offset(int i) const { assert(0 <= i && i < _num_verifier_constraints, "sanity"); @@ -134,6 +148,11 @@ private: assert(0 <= i && i < _num_loader_constraints, "sanity"); } + RTEnumKlassStaticFields* enum_klass_static_fields_addr() const { + assert(_klass->has_archived_enum_objs(), "sanity"); + return (RTEnumKlassStaticFields*)(address(this) + enum_klass_static_fields_offset()); + } + public: CrcInfo* crc() const { assert(crc_size(_klass) > 0, "must be"); @@ -187,6 +206,23 @@ public: return verifier_constraint_flags()[i]; } + int num_enum_klass_static_fields(int i) const { + return enum_klass_static_fields_addr()->_num; + } + + void set_num_enum_klass_static_fields(int num) { + enum_klass_static_fields_addr()->_num = num; + } + + int enum_klass_static_field_root_index_at(int i) const { + assert(0 <= i && i < enum_klass_static_fields_addr()->_num, "must be"); + return enum_klass_static_fields_addr()->_root_indices[i]; + } + + void set_enum_klass_static_field_root_index_at(int i, int root_index) { + assert(0 <= i && i < enum_klass_static_fields_addr()->_num, "must be"); + enum_klass_static_fields_addr()->_root_indices[i] = root_index; + } private: // ArchiveBuilder::make_shallow_copy() has reserved a pointer immediately // before archived InstanceKlasses. We can use this slot to do a quick diff --git a/src/hotspot/share/ci/ciStreams.cpp b/src/hotspot/share/ci/ciStreams.cpp index 1b9b6c7adf85c6895f9352f3df25250deea06892..6c7e9b6ee4171585bed3be470077722a2c77af27 100644 --- a/src/hotspot/share/ci/ciStreams.cpp +++ b/src/hotspot/share/ci/ciStreams.cpp @@ -256,6 +256,14 @@ constantTag ciBytecodeStream::get_constant_pool_tag(int index) const { return _method->get_Method()->constants()->constant_tag_at(index); } +// ------------------------------------------------------------------ +// ciBytecodeStream::get_raw_pool_tag +// +constantTag ciBytecodeStream::get_raw_pool_tag(int index) const { + VM_ENTRY_MARK; + return _method->get_Method()->constants()->tag_at(index); +} + // ------------------------------------------------------------------ // ciBytecodeStream::get_basic_type_for_constant_at // diff --git a/src/hotspot/share/ci/ciStreams.hpp b/src/hotspot/share/ci/ciStreams.hpp index e46b2e2bfa21fd5748fd3c6f6fe9ca0febdde9f9..faf3e87cee64f405315777e37c114a0bf9b792e5 100644 --- a/src/hotspot/share/ci/ciStreams.hpp +++ b/src/hotspot/share/ci/ciStreams.hpp @@ -230,12 +230,25 @@ public: constantTag get_constant_pool_tag(int index) const; BasicType get_basic_type_for_constant_at(int index) const; + constantTag get_raw_pool_tag(int index) const; + // True if the klass-using bytecode points to an unresolved klass bool is_unresolved_klass() const { constantTag tag = get_constant_pool_tag(get_klass_index()); return tag.is_unresolved_klass(); } + bool is_dynamic_constant() const { + assert(cur_bc() == Bytecodes::_ldc || + cur_bc() == Bytecodes::_ldc_w || + cur_bc() == Bytecodes::_ldc2_w, "not supported: %s", Bytecodes::name(cur_bc())); + + int index = get_constant_pool_index(); + constantTag tag = get_raw_pool_tag(index); + return tag.is_dynamic_constant() || + tag.is_dynamic_constant_in_error(); + } + bool is_in_error() const { assert(cur_bc() == Bytecodes::_ldc || cur_bc() == Bytecodes::_ldc_w || diff --git a/src/hotspot/share/classfile/classFileParser.cpp b/src/hotspot/share/classfile/classFileParser.cpp index 2325241dc64f7213d23b2ea3d0700a54da7a6102..182ed43bedf91a25aa7734f1d87e0f0fc2e41da4 100644 --- a/src/hotspot/share/classfile/classFileParser.cpp +++ b/src/hotspot/share/classfile/classFileParser.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -2741,6 +2741,7 @@ Method* ClassFileParser::parse_method(const ClassFileStream* const cfs, access_flags, &sizes, ConstMethod::NORMAL, + _cp->symbol_at(name_index), CHECK_NULL); ClassLoadingService::add_class_method_size(m->size()*wordSize); diff --git a/src/hotspot/share/classfile/defaultMethods.cpp b/src/hotspot/share/classfile/defaultMethods.cpp index 2ef313982d75037a580e7777b7e7667e121b05e1..4d181bdadf0dd1ad204b51c9566602aa648ad6bf 100644 --- a/src/hotspot/share/classfile/defaultMethods.cpp +++ b/src/hotspot/share/classfile/defaultMethods.cpp @@ -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 @@ -900,7 +900,7 @@ static Method* new_method( Method* m = Method::allocate(cp->pool_holder()->class_loader_data(), code_length, flags, &sizes, - mt, CHECK_NULL); + mt, name, CHECK_NULL); m->set_constants(NULL); // This will get filled in later m->set_name_index(cp->utf8(name)); diff --git a/src/hotspot/share/classfile/systemDictionary.cpp b/src/hotspot/share/classfile/systemDictionary.cpp index 195fa979ef996e793e55eca6474a90731efbd088..c3b9b0104431970b4fbc6272c40b9a4631b1b296 100644 --- a/src/hotspot/share/classfile/systemDictionary.cpp +++ b/src/hotspot/share/classfile/systemDictionary.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -1559,8 +1559,8 @@ InstanceKlass* SystemDictionary::find_or_define_instance_class(Symbol* class_nam // ---------------------------------------------------------------------------- -// Update hierachy. This is done before the new klass has been added to the SystemDictionary. The Compile_lock -// is held, to ensure that the compiler is not using the class hierachy, and that deoptimization will kick in +// Update hierarchy. This is done before the new klass has been added to the SystemDictionary. The Compile_lock +// is held, to ensure that the compiler is not using the class hierarchy, and that deoptimization will kick in // before a new class is used. void SystemDictionary::add_to_hierarchy(InstanceKlass* k) { @@ -1574,7 +1574,7 @@ void SystemDictionary::add_to_hierarchy(InstanceKlass* k) { // The compiler reads the hierarchy outside of the Compile_lock. // Access ordering is used to add to hierarchy. - // Link into hierachy. + // Link into hierarchy. k->append_to_sibling_list(); // add to superklass/sibling list k->process_interfaces(); // handle all "implements" declarations @@ -1724,7 +1724,7 @@ void SystemDictionary::check_constraints(unsigned int name_hash, } } -// Update class loader data dictionary - done after check_constraint and add_to_hierachy +// Update class loader data dictionary - done after check_constraint and add_to_hierarchy // have been called. void SystemDictionary::update_dictionary(unsigned int hash, InstanceKlass* k, @@ -2014,8 +2014,9 @@ Method* SystemDictionary::find_method_handle_intrinsic(vmIntrinsicID iid, spe = NULL; // Must create lots of stuff here, but outside of the SystemDictionary lock. m = Method::make_method_handle_intrinsic(iid, signature, CHECK_NULL); - if (!Arguments::is_interpreter_only()) { + if (!Arguments::is_interpreter_only() || iid == vmIntrinsics::_linkToNative) { // Generate a compiled form of the MH intrinsic. + // linkToNative doesn't have interpreter-specific implementation, so always has to go through compiled version. AdapterHandlerLibrary::create_native_wrapper(m); // Check if have the compiled code. if (!m->has_compiled_code()) { diff --git a/src/hotspot/share/classfile/systemDictionaryShared.cpp b/src/hotspot/share/classfile/systemDictionaryShared.cpp index 29b01851ac85651b64f706507591188dcfd443bd..66f9a433dfc097a23fb8909d9aa80900a6da47d2 100644 --- a/src/hotspot/share/classfile/systemDictionaryShared.cpp +++ b/src/hotspot/share/classfile/systemDictionaryShared.cpp @@ -793,6 +793,13 @@ bool SystemDictionaryShared::add_verification_constraint(InstanceKlass* k, Symbo } } +void SystemDictionaryShared::add_enum_klass_static_field(InstanceKlass* ik, int root_index) { + assert(DumpSharedSpaces, "static dump only"); + DumpTimeClassInfo* info = SystemDictionaryShared::find_or_allocate_info_for_locked(ik); + assert(info != NULL, "must be"); + info->add_enum_klass_static_field(root_index); +} + void SystemDictionaryShared::add_to_dump_time_lambda_proxy_class_dictionary(LambdaProxyClassKey& key, InstanceKlass* proxy_klass) { assert_lock_strong(DumpTimeTable_lock); @@ -1174,7 +1181,7 @@ public: bool do_entry(InstanceKlass* k, DumpTimeClassInfo& info) { if (!info.is_excluded()) { - size_t byte_size = RunTimeClassInfo::byte_size(info._klass, info.num_verifier_constraints(), info.num_loader_constraints()); + size_t byte_size = info.runtime_info_bytesize(); _shared_class_info_size += align_up(byte_size, SharedSpaceObjectAlignment); } return true; // keep on iterating @@ -1283,7 +1290,7 @@ public: bool do_entry(InstanceKlass* k, DumpTimeClassInfo& info) { if (!info.is_excluded() && info.is_builtin() == _is_builtin) { - size_t byte_size = RunTimeClassInfo::byte_size(info._klass, info.num_verifier_constraints(), info.num_loader_constraints()); + size_t byte_size = info.runtime_info_bytesize(); RunTimeClassInfo* record; record = (RunTimeClassInfo*)ArchiveBuilder::ro_region_alloc(byte_size); record->init(info); diff --git a/src/hotspot/share/classfile/systemDictionaryShared.hpp b/src/hotspot/share/classfile/systemDictionaryShared.hpp index a05484b429593149eaa55ec51dfe28f0dc830f91..0dbbd486dc37b92c39637f29eb360fc0c9265b7b 100644 --- a/src/hotspot/share/classfile/systemDictionaryShared.hpp +++ b/src/hotspot/share/classfile/systemDictionaryShared.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2021, 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 @@ -193,6 +193,9 @@ private: public: static bool is_hidden_lambda_proxy(InstanceKlass* ik); static bool is_early_klass(InstanceKlass* k); // Was k loaded while JvmtiExport::is_early_phase()==true + static bool has_archived_enum_objs(InstanceKlass* ik); + static void set_has_archived_enum_objs(InstanceKlass* ik); + static InstanceKlass* find_builtin_class(Symbol* class_name); static const RunTimeClassInfo* find_record(RunTimeSharedDictionary* static_dict, @@ -243,6 +246,7 @@ public: bool from_is_array, bool from_is_object) NOT_CDS_RETURN_(false); static void check_verification_constraints(InstanceKlass* klass, TRAPS) NOT_CDS_RETURN; + static void add_enum_klass_static_field(InstanceKlass* ik, int root_index); static void set_class_has_failed_verification(InstanceKlass* ik) NOT_CDS_RETURN; static bool has_class_failed_verification(InstanceKlass* ik) NOT_CDS_RETURN_(false); static void add_lambda_proxy_class(InstanceKlass* caller_ik, diff --git a/src/hotspot/share/classfile/vmClassMacros.hpp b/src/hotspot/share/classfile/vmClassMacros.hpp index 357e5538809fb83c2333608e1596922785a5e6e6..2879076004b5ad7a2d6f20593cf86f683997f3be 100644 --- a/src/hotspot/share/classfile/vmClassMacros.hpp +++ b/src/hotspot/share/classfile/vmClassMacros.hpp @@ -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 @@ -136,6 +136,7 @@ do_klass(ByteArrayInputStream_klass, java_io_ByteArrayInputStream ) \ do_klass(URL_klass, java_net_URL ) \ do_klass(URLClassLoader_klass, java_net_URLClassLoader ) \ + do_klass(Enum_klass, java_lang_Enum ) \ do_klass(Jar_Manifest_klass, java_util_jar_Manifest ) \ do_klass(jdk_internal_loader_BuiltinClassLoader_klass,jdk_internal_loader_BuiltinClassLoader ) \ do_klass(jdk_internal_loader_ClassLoaders_klass, jdk_internal_loader_ClassLoaders ) \ diff --git a/src/hotspot/share/classfile/vmIntrinsics.cpp b/src/hotspot/share/classfile/vmIntrinsics.cpp index cc3dc1ebdccf58fc689140cfcc02f432ec07dfef..a329669bed3d25b0a9284b4cce4482581faa9754 100644 --- a/src/hotspot/share/classfile/vmIntrinsics.cpp +++ b/src/hotspot/share/classfile/vmIntrinsics.cpp @@ -229,7 +229,7 @@ bool vmIntrinsics::disabled_by_jvm_flags(vmIntrinsics::ID id) { case vmIntrinsics::_loadFence: case vmIntrinsics::_storeFence: case vmIntrinsics::_fullFence: - case vmIntrinsics::_hasNegatives: + case vmIntrinsics::_countPositives: case vmIntrinsics::_Reference_get: break; default: diff --git a/src/hotspot/share/classfile/vmIntrinsics.hpp b/src/hotspot/share/classfile/vmIntrinsics.hpp index 7c3cb1d3f10235bcbb23d3363b930f98953a647d..5b2c6a9ce5610124d7de545ed690eb57dc9ea087 100644 --- a/src/hotspot/share/classfile/vmIntrinsics.hpp +++ b/src/hotspot/share/classfile/vmIntrinsics.hpp @@ -354,9 +354,9 @@ class methodHandle; do_signature(Preconditions_checkLongIndex_signature, "(JJLjava/util/function/BiFunction;)J") \ \ do_class(java_lang_StringCoding, "java/lang/StringCoding") \ - do_intrinsic(_hasNegatives, java_lang_StringCoding, hasNegatives_name, hasNegatives_signature, F_S) \ - do_name( hasNegatives_name, "hasNegatives") \ - do_signature(hasNegatives_signature, "([BII)Z") \ + do_intrinsic(_countPositives, java_lang_StringCoding, countPositives_name, countPositives_signature, F_S) \ + do_name( countPositives_name, "countPositives") \ + do_signature(countPositives_signature, "([BII)I") \ \ do_class(sun_nio_cs_iso8859_1_Encoder, "sun/nio/cs/ISO_8859_1$Encoder") \ do_intrinsic(_encodeISOArray, sun_nio_cs_iso8859_1_Encoder, encodeISOArray_name, encodeISOArray_signature, F_S) \ @@ -459,9 +459,8 @@ class methodHandle; \ /* support for sun.security.provider.DigestBase */ \ do_class(sun_security_provider_digestbase, "sun/security/provider/DigestBase") \ - do_intrinsic(_digestBase_implCompressMB, sun_security_provider_digestbase, implCompressMB_name, implCompressMB_signature, F_R) \ + do_intrinsic(_digestBase_implCompressMB, sun_security_provider_digestbase, implCompressMB_name, countPositives_signature, F_R) \ do_name( implCompressMB_name, "implCompressMultiBlock0") \ - do_signature(implCompressMB_signature, "([BII)I") \ \ /* support for java.util.Base64.Encoder*/ \ do_class(java_util_Base64_Encoder, "java/util/Base64$Encoder") \ diff --git a/src/hotspot/share/classfile/vmSymbols.hpp b/src/hotspot/share/classfile/vmSymbols.hpp index 65acd172f685ff9ad9dcd33e3f6331a6d74cbee2..e0402392467e2b9c9a19196798b5d755e569844e 100644 --- a/src/hotspot/share/classfile/vmSymbols.hpp +++ b/src/hotspot/share/classfile/vmSymbols.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -700,6 +700,7 @@ template(dumpSharedArchive_signature, "(ZLjava/lang/String;)Ljava/lang/String;") \ template(generateLambdaFormHolderClasses, "generateLambdaFormHolderClasses") \ template(generateLambdaFormHolderClasses_signature, "([Ljava/lang/String;)[Ljava/lang/Object;") \ + template(java_lang_Enum, "java/lang/Enum") \ template(java_lang_invoke_Invokers_Holder, "java/lang/invoke/Invokers$Holder") \ template(java_lang_invoke_DirectMethodHandle_Holder, "java/lang/invoke/DirectMethodHandle$Holder") \ template(java_lang_invoke_LambdaForm_Holder, "java/lang/invoke/LambdaForm$Holder") \ diff --git a/src/hotspot/share/code/codeCache.cpp b/src/hotspot/share/code/codeCache.cpp index 278792f2bc76619c9e79c9bcba3013dd82194023..0c1a579ea341c0658445dff0623f7290b6e484ec 100644 --- a/src/hotspot/share/code/codeCache.cpp +++ b/src/hotspot/share/code/codeCache.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2022, Oracle and/or its affiliates. All rights reserved. * 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,22 +101,37 @@ class CodeBlob_sizes { scopes_pcs_size = 0; } - int total() { return total_size; } - bool is_empty() { return count == 0; } + int total() const { return total_size; } + bool is_empty() const { return count == 0; } - void print(const char* title) { - tty->print_cr(" #%d %s = %dK (hdr %d%%, loc %d%%, code %d%%, stub %d%%, [oops %d%%, metadata %d%%, data %d%%, pcs %d%%])", - count, - title, - (int)(total() / K), - header_size * 100 / total_size, - relocation_size * 100 / total_size, - code_size * 100 / total_size, - stub_size * 100 / total_size, - scopes_oop_size * 100 / total_size, - scopes_metadata_size * 100 / total_size, - scopes_data_size * 100 / total_size, - scopes_pcs_size * 100 / total_size); + void print(const char* title) const { + if (is_empty()) { + tty->print_cr(" #%d %s = %dK", + count, + title, + total() / (int)K); + } else { + tty->print_cr(" #%d %s = %dK (hdr %dK %d%%, loc %dK %d%%, code %dK %d%%, stub %dK %d%%, [oops %dK %d%%, metadata %dK %d%%, data %dK %d%%, pcs %dK %d%%])", + count, + title, + total() / (int)K, + header_size / (int)K, + header_size * 100 / total_size, + relocation_size / (int)K, + relocation_size * 100 / total_size, + code_size / (int)K, + code_size * 100 / total_size, + stub_size / (int)K, + stub_size * 100 / total_size, + scopes_oop_size / (int)K, + scopes_oop_size * 100 / total_size, + scopes_metadata_size / (int)K, + scopes_metadata_size * 100 / total_size, + scopes_data_size / (int)K, + scopes_data_size * 100 / total_size, + scopes_pcs_size / (int)K, + scopes_pcs_size * 100 / total_size); + } } void add(CodeBlob* cb) { @@ -353,7 +368,7 @@ bool CodeCache::heap_available(int code_blob_type) { if (!SegmentedCodeCache) { // No segmentation: use a single code heap return (code_blob_type == CodeBlobType::All); - } else if (Arguments::is_interpreter_only()) { + } else if (CompilerConfig::is_interpreter_only()) { // Interpreter only: we don't need any method code heaps return (code_blob_type == CodeBlobType::NonNMethod); } else if (CompilerConfig::is_c1_profiling()) { @@ -487,7 +502,7 @@ CodeBlob* CodeCache::next_blob(CodeHeap* heap, CodeBlob* cb) { */ CodeBlob* CodeCache::allocate(int size, int code_blob_type, bool handle_alloc_failure, int orig_code_blob_type) { // Possibly wakes up the sweeper thread. - NMethodSweeper::report_allocation(code_blob_type); + NMethodSweeper::report_allocation(); assert_locked_or_safepoint(CodeCache_lock); assert(size > 0, "Code cache allocation request must be > 0 but is %d", size); if (size <= 0) { @@ -512,7 +527,7 @@ CodeBlob* CodeCache::allocate(int size, int code_blob_type, bool handle_alloc_fa // Fallback solution: Try to store code in another code heap. // NonNMethod -> MethodNonProfiled -> MethodProfiled (-> MethodNonProfiled) // Note that in the sweeper, we check the reverse_free_ratio of the code heap - // and force stack scanning if less than 10% of the code heap are free. + // and force stack scanning if less than 10% of the entire code cache are free. int type = code_blob_type; switch (type) { case CodeBlobType::NonNMethod: @@ -889,20 +904,17 @@ size_t CodeCache::max_capacity() { return max_cap; } -/** - * Returns the reverse free ratio. E.g., if 25% (1/4) of the code heap - * is free, reverse_free_ratio() returns 4. - */ -double CodeCache::reverse_free_ratio(int code_blob_type) { - CodeHeap* heap = get_code_heap(code_blob_type); - if (heap == NULL) { - return 0; - } - double unallocated_capacity = MAX2((double)heap->unallocated_capacity(), 1.0); // Avoid division by 0; - double max_capacity = (double)heap->max_capacity(); - double result = max_capacity / unallocated_capacity; - assert (max_capacity >= unallocated_capacity, "Must be"); +// Returns the reverse free ratio. E.g., if 25% (1/4) of the code cache +// is free, reverse_free_ratio() returns 4. +// Since code heap for each type of code blobs falls forward to the next +// type of code heap, return the reverse free ratio for the entire +// code cache. +double CodeCache::reverse_free_ratio() { + double unallocated = MAX2((double)unallocated_capacity(), 1.0); // Avoid division by 0; + double max = (double)max_capacity(); + double result = max / unallocated; + assert (max >= unallocated, "Must be"); assert (result >= 1.0, "reverse_free_ratio must be at least 1. It is %f", result); return result; } @@ -1226,9 +1238,9 @@ void CodeCache::report_codemem_full(int code_blob_type, bool print) { CodeHeap* heap = get_code_heap(code_blob_type); assert(heap != NULL, "heap is null"); - heap->report_full(); + int full_count = heap->report_full(); - if ((heap->full_count() == 1) || print) { + if ((full_count == 1) || print) { // Not yet reported for this heap, report if (SegmentedCodeCache) { ResourceMark rm; @@ -1265,7 +1277,7 @@ void CodeCache::report_codemem_full(int code_blob_type, bool print) { tty->print("%s", s.as_string()); } - if (heap->full_count() == 1) { + if (full_count == 1) { if (PrintCodeHeapAnalytics) { CompileBroker::print_heapinfo(tty, "all", 4096); // details, may be a lot! } @@ -1430,27 +1442,73 @@ void CodeCache::print() { #ifndef PRODUCT if (!Verbose) return; - CodeBlob_sizes live; - CodeBlob_sizes dead; + CodeBlob_sizes live[CompLevel_full_optimization + 1]; + CodeBlob_sizes dead[CompLevel_full_optimization + 1]; + CodeBlob_sizes runtimeStub; + CodeBlob_sizes uncommonTrapStub; + CodeBlob_sizes deoptimizationStub; + CodeBlob_sizes adapter; + CodeBlob_sizes bufferBlob; + CodeBlob_sizes other; FOR_ALL_ALLOCABLE_HEAPS(heap) { FOR_ALL_BLOBS(cb, *heap) { - if (!cb->is_alive()) { - dead.add(cb); + if (cb->is_nmethod()) { + const int level = cb->as_nmethod()->comp_level(); + assert(0 <= level && level <= CompLevel_full_optimization, "Invalid compilation level"); + if (!cb->is_alive()) { + dead[level].add(cb); + } else { + live[level].add(cb); + } + } else if (cb->is_runtime_stub()) { + runtimeStub.add(cb); + } else if (cb->is_deoptimization_stub()) { + deoptimizationStub.add(cb); + } else if (cb->is_uncommon_trap_stub()) { + uncommonTrapStub.add(cb); + } else if (cb->is_adapter_blob()) { + adapter.add(cb); + } else if (cb->is_buffer_blob()) { + bufferBlob.add(cb); } else { - live.add(cb); + other.add(cb); } } } - tty->print_cr("CodeCache:"); tty->print_cr("nmethod dependency checking time %fs", dependentCheckTime.seconds()); - if (!live.is_empty()) { - live.print("live"); - } - if (!dead.is_empty()) { - dead.print("dead"); + tty->print_cr("nmethod blobs per compilation level:"); + for (int i = 0; i <= CompLevel_full_optimization; i++) { + const char *level_name; + switch (i) { + case CompLevel_none: level_name = "none"; break; + case CompLevel_simple: level_name = "simple"; break; + case CompLevel_limited_profile: level_name = "limited profile"; break; + case CompLevel_full_profile: level_name = "full profile"; break; + case CompLevel_full_optimization: level_name = "full optimization"; break; + default: assert(false, "invalid compilation level"); + } + tty->print_cr("%s:", level_name); + live[i].print("live"); + dead[i].print("dead"); + } + + struct { + const char* name; + const CodeBlob_sizes* sizes; + } non_nmethod_blobs[] = { + { "runtime", &runtimeStub }, + { "uncommon trap", &uncommonTrapStub }, + { "deoptimization", &deoptimizationStub }, + { "adapter", &adapter }, + { "buffer blob", &bufferBlob }, + { "other", &other }, + }; + tty->print_cr("Non-nmethod blobs:"); + for (auto& blob: non_nmethod_blobs) { + blob.sizes->print(blob.name); } if (WizardMode) { diff --git a/src/hotspot/share/code/codeCache.hpp b/src/hotspot/share/code/codeCache.hpp index 53705aadcbe3639aca98e21beeacb1cd9d2d5e8c..0a0bd9c770402e450dc51330033a0f7dbb840b44 100644 --- a/src/hotspot/share/code/codeCache.hpp +++ b/src/hotspot/share/code/codeCache.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -211,7 +211,7 @@ class CodeCache : AllStatic { static size_t unallocated_capacity(); static size_t max_capacity(); - static double reverse_free_ratio(int code_blob_type); + static double reverse_free_ratio(); static void clear_inline_caches(); // clear all inline caches static void cleanup_inline_caches(); // clean unloaded/zombie nmethods from inline caches diff --git a/src/hotspot/share/compiler/compilationPolicy.cpp b/src/hotspot/share/compiler/compilationPolicy.cpp index 592cb5d65f2f400feb94fd75bced2012a7da7ffd..027b513af695544695ff82d4458bf469abe45ae2 100644 --- a/src/hotspot/share/compiler/compilationPolicy.cpp +++ b/src/hotspot/share/compiler/compilationPolicy.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2021, 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 @@ -315,7 +315,7 @@ double CompilationPolicy::threshold_scale(CompLevel level, int feedback_k) { // The main intention is to keep enough free space for C2 compiled code // to achieve peak performance if the code cache is under stress. if (CompilerConfig::is_tiered() && !CompilationModeFlag::disable_intermediate() && is_c1_compile(level)) { - double current_reverse_free_ratio = CodeCache::reverse_free_ratio(CodeCache::get_code_blob_type(level)); + double current_reverse_free_ratio = CodeCache::reverse_free_ratio(); if (current_reverse_free_ratio > _increase_threshold_at_ratio) { k *= exp(current_reverse_free_ratio - _increase_threshold_at_ratio); } diff --git a/src/hotspot/share/compiler/compileBroker.cpp b/src/hotspot/share/compiler/compileBroker.cpp index 1c8656044b57b3a352b4422ea0cd219173b373f2..6422b719f68de41530e3139ea55b113f510414e8 100644 --- a/src/hotspot/share/compiler/compileBroker.cpp +++ b/src/hotspot/share/compiler/compileBroker.cpp @@ -225,11 +225,13 @@ class CompilationLog : public StringEventLog { } void log_metaspace_failure(const char* reason) { + // Note: This method can be called from non-Java/compiler threads to + // log the global metaspace failure that might affect profiling. ResourceMark rm; StringLogMessage lm; lm.print("%4d COMPILE PROFILING SKIPPED: %s", -1, reason); lm.print("\n"); - log(JavaThread::current(), "%s", (const char*)lm); + log(Thread::current(), "%s", (const char*)lm); } }; diff --git a/src/hotspot/share/compiler/compilerDefinitions.cpp b/src/hotspot/share/compiler/compilerDefinitions.cpp index a6445c161b2f3593ae2203f4b62bde89c14d4428..aa8dd0a1be8638c9bc4519177af24624da36744c 100644 --- a/src/hotspot/share/compiler/compilerDefinitions.cpp +++ b/src/hotspot/share/compiler/compilerDefinitions.cpp @@ -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 @@ -310,7 +310,6 @@ void CompilerConfig::set_compilation_policy_flags() { } } - if (CompileThresholdScaling < 0) { vm_exit_during_initialization("Negative value specified for CompileThresholdScaling", NULL); } @@ -509,6 +508,10 @@ bool CompilerConfig::check_args_consistency(bool status) { } FLAG_SET_CMDLINE(TieredCompilation, false); } + if (SegmentedCodeCache) { + warning("SegmentedCodeCache has no meaningful effect with -Xint"); + FLAG_SET_DEFAULT(SegmentedCodeCache, false); + } #if INCLUDE_JVMCI if (EnableJVMCI) { if (!FLAG_IS_DEFAULT(EnableJVMCI) || !FLAG_IS_DEFAULT(UseJVMCICompiler)) { diff --git a/src/hotspot/share/compiler/compilerDirectives.hpp b/src/hotspot/share/compiler/compilerDirectives.hpp index 1e1bf850ac36b00f49ae437e0311963ec0ab50f2..bab28e2458ae0c5bd4bd120cf006fd617dc856ca 100644 --- a/src/hotspot/share/compiler/compilerDirectives.hpp +++ b/src/hotspot/share/compiler/compilerDirectives.hpp @@ -66,6 +66,7 @@ cflags(PrintIntrinsics, bool, PrintIntrinsics, PrintIntrinsics) \ NOT_PRODUCT(cflags(TraceOptoPipelining, bool, TraceOptoPipelining, TraceOptoPipelining)) \ NOT_PRODUCT(cflags(TraceOptoOutput, bool, TraceOptoOutput, TraceOptoOutput)) \ +NOT_PRODUCT(cflags(TraceEscapeAnalysis, bool, false, TraceEscapeAnalysis)) \ NOT_PRODUCT(cflags(PrintIdeal, bool, PrintIdeal, PrintIdeal)) \ NOT_PRODUCT(cflags(PrintIdealPhase, ccstrlist, "", PrintIdealPhase)) \ cflags(TraceSpilling, bool, TraceSpilling, TraceSpilling) \ diff --git a/src/hotspot/share/compiler/compilerOracle.hpp b/src/hotspot/share/compiler/compilerOracle.hpp index ab941b01d88b5d755ea0edc03e7f705a0587e788..303c52683f543e435b3eab1fbdd03d3d2d05b7a3 100644 --- a/src/hotspot/share/compiler/compilerOracle.hpp +++ b/src/hotspot/share/compiler/compilerOracle.hpp @@ -79,6 +79,7 @@ class methodHandle; option(TraceOptoPipelining, "TraceOptoPipelining", Bool) \ option(TraceOptoOutput, "TraceOptoOutput", Bool) \ option(TraceSpilling, "TraceSpilling", Bool) \ +NOT_PRODUCT(option(TraceEscapeAnalysis, "TraceEscapeAnalysis", Bool)) \ NOT_PRODUCT(option(PrintIdeal, "PrintIdeal", Bool)) \ NOT_PRODUCT(option(PrintIdealPhase, "PrintIdealPhase", Ccstrlist)) \ NOT_PRODUCT(option(IGVPrintLevel, "IGVPrintLevel", Intx)) \ diff --git a/src/hotspot/share/gc/g1/g1BlockOffsetTable.inline.hpp b/src/hotspot/share/gc/g1/g1BlockOffsetTable.inline.hpp index f70cb118627225f646cb43345c44b4a5a37cb085..058a9f58785dfd978e02ddd5dbab961159e75276 100644 --- a/src/hotspot/share/gc/g1/g1BlockOffsetTable.inline.hpp +++ b/src/hotspot/share/gc/g1/g1BlockOffsetTable.inline.hpp @@ -140,7 +140,7 @@ inline HeapWord* G1BlockOffsetTablePart::forward_to_block_containing_addr(HeapWo "start of block must be an initialized object"); n += block_size(q); } - assert(q <= n, "wrong order for q and addr"); + assert(q <= addr, "wrong order for q and addr"); assert(addr < n, "wrong order for addr and n"); return q; } diff --git a/src/hotspot/share/gc/g1/g1CardSet.cpp b/src/hotspot/share/gc/g1/g1CardSet.cpp index ad886b1e7e6baa7c3016605dd19926336aeecb23..82092a1d5020c9d17b5af25c947757365ce4e240 100644 --- a/src/hotspot/share/gc/g1/g1CardSet.cpp +++ b/src/hotspot/share/gc/g1/g1CardSet.cpp @@ -26,25 +26,19 @@ #include "gc/g1/g1CardSet.inline.hpp" #include "gc/g1/g1CardSetContainers.inline.hpp" #include "gc/g1/g1CardSetMemory.inline.hpp" -#include "gc/g1/g1FromCardCache.hpp" #include "gc/g1/heapRegion.inline.hpp" +#include "gc/shared/gcLogPrecious.hpp" +#include "gc/shared/gcTraceTime.inline.hpp" #include "memory/allocation.inline.hpp" #include "runtime/atomic.hpp" #include "runtime/globals_extension.hpp" -#include "runtime/mutex.hpp" #include "utilities/bitMap.inline.hpp" #include "utilities/concurrentHashTable.inline.hpp" #include "utilities/globalDefinitions.hpp" -#include "utilities/lockFreeStack.hpp" -#include "utilities/spinYield.hpp" - -#include "gc/shared/gcLogPrecious.hpp" -#include "gc/shared/gcTraceTime.inline.hpp" -#include "runtime/java.hpp" -G1CardSet::CardSetPtr G1CardSet::FullCardSet = (G1CardSet::CardSetPtr)-1; +G1CardSet::ContainerPtr G1CardSet::FullCardSet = (G1CardSet::ContainerPtr)-1; -static uint default_log2_card_region_per_region() { +static uint default_log2_card_regions_per_region() { uint log2_card_regions_per_heap_region = 0; const uint card_container_limit = G1CardSetContainer::LogCardsPerRegionLimit; @@ -62,7 +56,7 @@ G1CardSetConfiguration::G1CardSetConfiguration() : G1RemSetHowlNumBuckets, /* num_buckets_in_howl */ (double)G1RemSetCoarsenHowlToFullPercent / 100, /* cards_in_howl_threshold_percent */ (uint)HeapRegion::CardsPerRegion, /* max_cards_in_cardset */ - default_log2_card_region_per_region()) /* log2_card_region_per_region */ + default_log2_card_regions_per_region()) /* log2_card_regions_per_region */ { assert((_log2_card_regions_per_heap_region + _log2_cards_per_card_region) == (uint)HeapRegion::LogCardsPerRegion, "inconsistent heap region virtualization setup"); @@ -73,7 +67,7 @@ G1CardSetConfiguration::G1CardSetConfiguration(uint max_cards_in_array, uint max_buckets_in_howl, double cards_in_howl_threshold_percent, uint max_cards_in_card_set, - uint log2_card_region_per_region) : + uint log2_card_regions_per_region) : G1CardSetConfiguration(log2i_exact(max_cards_in_card_set), /* inline_ptr_bits_per_card */ max_cards_in_array, /* max_cards_in_array */ cards_in_bitmap_threshold_percent, /* cards_in_bitmap_threshold_percent */ @@ -82,7 +76,7 @@ G1CardSetConfiguration::G1CardSetConfiguration(uint max_cards_in_array, max_buckets_in_howl), cards_in_howl_threshold_percent, /* cards_in_howl_threshold_percent */ max_cards_in_card_set, /* max_cards_in_cardset */ - log2_card_region_per_region) + log2_card_regions_per_region) { } G1CardSetConfiguration::G1CardSetConfiguration(uint inline_ptr_bits_per_card, @@ -197,7 +191,7 @@ void G1CardSetCoarsenStats::print_on(outputStream* out) { } class G1CardSetHashTable : public CHeapObj { - using CardSetPtr = G1CardSet::CardSetPtr; + using ContainerPtr = G1CardSet::ContainerPtr; // Did we insert at least one card in the table? bool volatile _inserted_card; @@ -231,12 +225,12 @@ class G1CardSetHashTable : public CHeapObj { }; class G1CardSetHashTableScan : public StackObj { - G1CardSet::CardSetPtrClosure* _scan_f; + G1CardSet::ContainerPtrClosure* _scan_f; public: - explicit G1CardSetHashTableScan(G1CardSet::CardSetPtrClosure* f) : _scan_f(f) { } + explicit G1CardSetHashTableScan(G1CardSet::ContainerPtrClosure* f) : _scan_f(f) { } bool operator()(G1CardSetHashTableValue* value) { - _scan_f->do_cardsetptr(value->_region_idx, value->_num_occupied, value->_card_set); + _scan_f->do_containerptr(value->_region_idx, value->_num_occupied, value->_container); return true; } }; @@ -284,19 +278,19 @@ public: return found.value(); } - void iterate_safepoint(G1CardSet::CardSetPtrClosure* cl2) { + void iterate_safepoint(G1CardSet::ContainerPtrClosure* cl2) { G1CardSetHashTableScan cl(cl2); _table.do_safepoint_scan(cl); } - void iterate(G1CardSet::CardSetPtrClosure* cl2) { + void iterate(G1CardSet::ContainerPtrClosure* cl2) { G1CardSetHashTableScan cl(cl2); _table.do_scan(Thread::current(), cl); } void reset() { if (Atomic::load(&_inserted_card)) { - _table.unsafe_reset(InitialLogTableSize); + _table.unsafe_reset(InitialLogTableSize); Atomic::store(&_inserted_card, false); } } @@ -343,101 +337,93 @@ G1CardSet::~G1CardSet() { _mm->flush(); } -uint G1CardSet::card_set_type_to_mem_object_type(uintptr_t type) const { - assert(type == G1CardSet::CardSetArrayOfCards || - type == G1CardSet::CardSetBitMap || - type == G1CardSet::CardSetHowl, "should not allocate card set type %zu", type); +uint G1CardSet::container_type_to_mem_object_type(uintptr_t type) const { + assert(type == G1CardSet::ContainerArrayOfCards || + type == G1CardSet::ContainerBitMap || + type == G1CardSet::ContainerHowl, "should not allocate container type %zu", type); return (uint)type; } uint8_t* G1CardSet::allocate_mem_object(uintptr_t type) { - return _mm->allocate(card_set_type_to_mem_object_type(type)); + return _mm->allocate(container_type_to_mem_object_type(type)); } -void G1CardSet::free_mem_object(CardSetPtr card_set) { - assert(card_set != G1CardSet::FreeCardSet, "should not free Free card set"); - assert(card_set != G1CardSet::FullCardSet, "should not free Full card set"); +void G1CardSet::free_mem_object(ContainerPtr container) { + assert(container != G1CardSet::FreeCardSet, "should not free container FreeCardSet"); + assert(container != G1CardSet::FullCardSet, "should not free container FullCardSet"); - uintptr_t type = card_set_type(card_set); - void* value = strip_card_set_type(card_set); + uintptr_t type = container_type(container); + void* value = strip_container_type(container); - assert(type == G1CardSet::CardSetArrayOfCards || - type == G1CardSet::CardSetBitMap || - type == G1CardSet::CardSetHowl, "should not free card set type %zu", type); + assert(type == G1CardSet::ContainerArrayOfCards || + type == G1CardSet::ContainerBitMap || + type == G1CardSet::ContainerHowl, "should not free card set type %zu", type); + assert(static_cast(value)->refcount() == 1, "must be"); -#ifdef ASSERT - if (type == G1CardSet::CardSetArrayOfCards || - type == G1CardSet::CardSetBitMap || - type == G1CardSet::CardSetHowl) { - G1CardSetContainer* card_set = (G1CardSetContainer*)value; - assert((card_set->refcount() == 1), "must be"); - } -#endif - - _mm->free(card_set_type_to_mem_object_type(type), value); + _mm->free(container_type_to_mem_object_type(type), value); } -G1CardSet::CardSetPtr G1CardSet::acquire_card_set(CardSetPtr volatile* card_set_addr) { +G1CardSet::ContainerPtr G1CardSet::acquire_container(ContainerPtr volatile* container_addr) { // Update reference counts under RCU critical section to avoid a // use-after-cleapup bug where we increment a reference count for // an object whose memory has already been cleaned up and reused. GlobalCounter::CriticalSection cs(Thread::current()); while (true) { - // Get cardsetptr and increment refcount atomically wrt to memory reuse. - CardSetPtr card_set = Atomic::load_acquire(card_set_addr); - uint cs_type = card_set_type(card_set); - if (card_set == FullCardSet || cs_type == CardSetInlinePtr) { - return card_set; + // Get ContainerPtr and increment refcount atomically wrt to memory reuse. + ContainerPtr container = Atomic::load_acquire(container_addr); + uint cs_type = container_type(container); + if (container == FullCardSet || cs_type == ContainerInlinePtr) { + return container; } - G1CardSetContainer* card_set_on_heap = (G1CardSetContainer*)strip_card_set_type(card_set); + G1CardSetContainer* container_on_heap = (G1CardSetContainer*)strip_container_type(container); - if (card_set_on_heap->try_increment_refcount()) { - assert(card_set_on_heap->refcount() >= 3, "Smallest value is 3"); - return card_set; + if (container_on_heap->try_increment_refcount()) { + assert(container_on_heap->refcount() >= 3, "Smallest value is 3"); + return container; } } } -bool G1CardSet::release_card_set(CardSetPtr card_set) { - uint cs_type = card_set_type(card_set); - if (card_set == FullCardSet || cs_type == CardSetInlinePtr) { +bool G1CardSet::release_container(ContainerPtr container) { + uint cs_type = container_type(container); + if (container == FullCardSet || cs_type == ContainerInlinePtr) { return false; } - G1CardSetContainer* card_set_on_heap = (G1CardSetContainer*)strip_card_set_type(card_set); - return card_set_on_heap->decrement_refcount() == 1; + G1CardSetContainer* container_on_heap = (G1CardSetContainer*)strip_container_type(container); + return container_on_heap->decrement_refcount() == 1; } -void G1CardSet::release_and_maybe_free_card_set(CardSetPtr card_set) { - if (release_card_set(card_set)) { - free_mem_object(card_set); +void G1CardSet::release_and_maybe_free_container(ContainerPtr container) { + if (release_container(container)) { + free_mem_object(container); } } -void G1CardSet::release_and_must_free_card_set(CardSetPtr card_set) { - bool should_free = release_card_set(card_set); +void G1CardSet::release_and_must_free_container(ContainerPtr container) { + bool should_free = release_container(container); assert(should_free, "should have been the only one having a reference"); - free_mem_object(card_set); + free_mem_object(container); } class G1ReleaseCardsets : public StackObj { G1CardSet* _card_set; - using CardSetPtr = G1CardSet::CardSetPtr; + using ContainerPtr = G1CardSet::ContainerPtr; - void coarsen_to_full(CardSetPtr* card_set_addr) { + void coarsen_to_full(ContainerPtr* container_addr) { while (true) { - CardSetPtr cur_card_set = Atomic::load_acquire(card_set_addr); - uint cs_type = G1CardSet::card_set_type(cur_card_set); - if (cur_card_set == G1CardSet::FullCardSet) { + ContainerPtr cur_container = Atomic::load_acquire(container_addr); + uint cs_type = G1CardSet::container_type(cur_container); + if (cur_container == G1CardSet::FullCardSet) { return; } - CardSetPtr old_value = Atomic::cmpxchg(card_set_addr, cur_card_set, G1CardSet::FullCardSet); + ContainerPtr old_value = Atomic::cmpxchg(container_addr, cur_container, G1CardSet::FullCardSet); - if (old_value == cur_card_set) { - _card_set->release_and_maybe_free_card_set(cur_card_set); + if (old_value == cur_container) { + _card_set->release_and_maybe_free_container(cur_container); return; } } @@ -446,51 +432,51 @@ class G1ReleaseCardsets : public StackObj { public: explicit G1ReleaseCardsets(G1CardSet* card_set) : _card_set(card_set) { } - void operator ()(CardSetPtr* card_set_addr) { - coarsen_to_full(card_set_addr); + void operator ()(ContainerPtr* container_addr) { + coarsen_to_full(container_addr); } }; -G1AddCardResult G1CardSet::add_to_array(CardSetPtr card_set, uint card_in_region) { - G1CardSetArray* array = card_set_ptr(card_set); +G1AddCardResult G1CardSet::add_to_array(ContainerPtr container, uint card_in_region) { + G1CardSetArray* array = container_ptr(container); return array->add(card_in_region); } -G1AddCardResult G1CardSet::add_to_howl(CardSetPtr parent_card_set, - uint card_region, - uint card_in_region, - bool increment_total) { - G1CardSetHowl* howl = card_set_ptr(parent_card_set); +G1AddCardResult G1CardSet::add_to_howl(ContainerPtr parent_container, + uint card_region, + uint card_in_region, + bool increment_total) { + G1CardSetHowl* howl = container_ptr(parent_container); G1AddCardResult add_result; - CardSetPtr to_transfer = nullptr; - CardSetPtr card_set; + ContainerPtr to_transfer = nullptr; + ContainerPtr container; uint bucket = _config->howl_bucket_index(card_in_region); - volatile CardSetPtr* bucket_entry = howl->get_card_set_addr(bucket); + ContainerPtr volatile* bucket_entry = howl->get_container_addr(bucket); while (true) { if (Atomic::load(&howl->_num_entries) >= _config->cards_in_howl_threshold()) { return Overflow; } - card_set = acquire_card_set(bucket_entry); - add_result = add_to_card_set(bucket_entry, card_set, card_region, card_in_region); + container = acquire_container(bucket_entry); + add_result = add_to_container(bucket_entry, container, card_region, card_in_region); if (add_result != Overflow) { break; } - // Card set has overflown. Coarsen or retry. - bool coarsened = coarsen_card_set(bucket_entry, card_set, card_in_region, true /* within_howl */); - _coarsen_stats.record_coarsening(card_set_type(card_set) + G1CardSetCoarsenStats::CoarsenHowlOffset, !coarsened); + // Card set container has overflown. Coarsen or retry. + bool coarsened = coarsen_container(bucket_entry, container, card_in_region, true /* within_howl */); + _coarsen_stats.record_coarsening(container_type(container) + G1CardSetCoarsenStats::CoarsenHowlOffset, !coarsened); if (coarsened) { - // We have been the one coarsening this card set (and in the process added that card). + // We successful coarsened this card set container (and in the process added the card). add_result = Added; - to_transfer = card_set; + to_transfer = container; break; } // Somebody else beat us to coarsening. Retry. - release_and_maybe_free_card_set(card_set); + release_and_maybe_free_container(container); } if (increment_total && add_result == Added) { @@ -498,91 +484,91 @@ G1AddCardResult G1CardSet::add_to_howl(CardSetPtr parent_card_set, } if (to_transfer != nullptr) { - transfer_cards_in_howl(parent_card_set, to_transfer, card_region); + transfer_cards_in_howl(parent_container, to_transfer, card_region); } - release_and_maybe_free_card_set(card_set); + release_and_maybe_free_container(container); return add_result; } -G1AddCardResult G1CardSet::add_to_bitmap(CardSetPtr card_set, uint card_in_region) { - G1CardSetBitMap* bitmap = card_set_ptr(card_set); +G1AddCardResult G1CardSet::add_to_bitmap(ContainerPtr container, uint card_in_region) { + G1CardSetBitMap* bitmap = container_ptr(container); uint card_offset = _config->howl_bitmap_offset(card_in_region); return bitmap->add(card_offset, _config->cards_in_howl_bitmap_threshold(), _config->max_cards_in_howl_bitmap()); } -G1AddCardResult G1CardSet::add_to_inline_ptr(CardSetPtr volatile* card_set_addr, CardSetPtr card_set, uint card_in_region) { - G1CardSetInlinePtr value(card_set_addr, card_set); +G1AddCardResult G1CardSet::add_to_inline_ptr(ContainerPtr volatile* container_addr, ContainerPtr container, uint card_in_region) { + G1CardSetInlinePtr value(container_addr, container); return value.add(card_in_region, _config->inline_ptr_bits_per_card(), _config->max_cards_in_inline_ptr()); } -G1CardSet::CardSetPtr G1CardSet::create_coarsened_array_of_cards(uint card_in_region, bool within_howl) { +G1CardSet::ContainerPtr G1CardSet::create_coarsened_array_of_cards(uint card_in_region, bool within_howl) { uint8_t* data = nullptr; - CardSetPtr new_card_set; + ContainerPtr new_container; if (within_howl) { uint const size_in_bits = _config->max_cards_in_howl_bitmap(); - uint card_offset = _config->howl_bitmap_offset(card_in_region); - data = allocate_mem_object(CardSetBitMap); - new (data) G1CardSetBitMap(card_offset, size_in_bits); - new_card_set = make_card_set_ptr(data, CardSetBitMap); + uint container_offset = _config->howl_bitmap_offset(card_in_region); + data = allocate_mem_object(ContainerBitMap); + new (data) G1CardSetBitMap(container_offset, size_in_bits); + new_container = make_container_ptr(data, ContainerBitMap); } else { - data = allocate_mem_object(CardSetHowl); + data = allocate_mem_object(ContainerHowl); new (data) G1CardSetHowl(card_in_region, _config); - new_card_set = make_card_set_ptr(data, CardSetHowl); + new_container = make_container_ptr(data, ContainerHowl); } - return new_card_set; + return new_container; } -bool G1CardSet::coarsen_card_set(volatile CardSetPtr* card_set_addr, - CardSetPtr cur_card_set, - uint card_in_region, - bool within_howl) { - CardSetPtr new_card_set = nullptr; +bool G1CardSet::coarsen_container(ContainerPtr volatile* container_addr, + ContainerPtr cur_container, + uint card_in_region, + bool within_howl) { + ContainerPtr new_container = nullptr; - switch (card_set_type(cur_card_set)) { - case CardSetArrayOfCards : { - new_card_set = create_coarsened_array_of_cards(card_in_region, within_howl); + switch (container_type(cur_container)) { + case ContainerArrayOfCards: { + new_container = create_coarsened_array_of_cards(card_in_region, within_howl); break; } - case CardSetBitMap: { - new_card_set = FullCardSet; + case ContainerBitMap: { + new_container = FullCardSet; break; } - case CardSetInlinePtr: { + case ContainerInlinePtr: { uint const size = _config->max_cards_in_array(); - uint8_t* data = allocate_mem_object(CardSetArrayOfCards); + uint8_t* data = allocate_mem_object(ContainerArrayOfCards); new (data) G1CardSetArray(card_in_region, size); - new_card_set = make_card_set_ptr(data, CardSetArrayOfCards); + new_container = make_container_ptr(data, ContainerArrayOfCards); break; } - case CardSetHowl: { - new_card_set = FullCardSet; // anything will do at this point. + case ContainerHowl: { + new_container = FullCardSet; // anything will do at this point. break; } default: ShouldNotReachHere(); } - CardSetPtr old_value = Atomic::cmpxchg(card_set_addr, cur_card_set, new_card_set); // Memory order? - if (old_value == cur_card_set) { + ContainerPtr old_value = Atomic::cmpxchg(container_addr, cur_container, new_container); // Memory order? + if (old_value == cur_container) { // Success. Indicate that the cards from the current card set must be transferred // by this caller. // Release the hash table reference to the card. The caller still holds the // reference to this card set, so it can never be released (and we do not need to // check its result). - bool should_free = release_card_set(cur_card_set); + bool should_free = release_container(cur_container); assert(!should_free, "must have had more than one reference"); - // Free containers if cur_card_set is CardSetHowl - if (card_set_type(cur_card_set) == CardSetHowl) { + // Free containers if cur_container is ContainerHowl + if (container_type(cur_container) == ContainerHowl) { G1ReleaseCardsets rel(this); - card_set_ptr(cur_card_set)->iterate(rel, _config->num_buckets_in_howl()); + container_ptr(cur_container)->iterate(rel, _config->num_buckets_in_howl()); } return true; } else { // Somebody else beat us to coarsening that card set. Exit, but clean up first. - if (new_card_set != FullCardSet) { - assert(new_card_set != nullptr, "must not be"); - release_and_must_free_card_set(new_card_set); + if (new_container != FullCardSet) { + assert(new_container != nullptr, "must not be"); + release_and_must_free_container(new_container); } return false; } @@ -599,34 +585,34 @@ public: } }; -void G1CardSet::transfer_cards(G1CardSetHashTableValue* table_entry, CardSetPtr source_card_set, uint card_region) { - assert(source_card_set != FullCardSet, "Should not need to transfer from full"); - // Need to transfer old entries unless there is a Full card set in place now, i.e. - // the old type has been CardSetBitMap. "Full" contains all elements anyway. - if (card_set_type(source_card_set) != CardSetHowl) { +void G1CardSet::transfer_cards(G1CardSetHashTableValue* table_entry, ContainerPtr source_container, uint card_region) { + assert(source_container != FullCardSet, "Should not need to transfer from FullCardSet"); + // Need to transfer old entries unless there is a Full card set container in place now, i.e. + // the old type has been ContainerBitMap. "Full" contains all elements anyway. + if (container_type(source_container) != ContainerHowl) { G1TransferCard iter(this, card_region); - iterate_cards_during_transfer(source_card_set, iter); + iterate_cards_during_transfer(source_container, iter); } else { - assert(card_set_type(source_card_set) == CardSetHowl, "must be"); + assert(container_type(source_container) == ContainerHowl, "must be"); // Need to correct for that the Full remembered set occupies more cards than the // AoCS before. Atomic::add(&_num_occupied, _config->max_cards_in_region() - table_entry->_num_occupied, memory_order_relaxed); } } -void G1CardSet::transfer_cards_in_howl(CardSetPtr parent_card_set, - CardSetPtr source_card_set, - uint card_region) { - assert(card_set_type(parent_card_set) == CardSetHowl, "must be"); - assert(source_card_set != FullCardSet, "Should not need to transfer from full"); +void G1CardSet::transfer_cards_in_howl(ContainerPtr parent_container, + ContainerPtr source_container, + uint card_region) { + assert(container_type(parent_container) == ContainerHowl, "must be"); + assert(source_container != FullCardSet, "Should not need to transfer from full"); // Need to transfer old entries unless there is a Full card set in place now, i.e. - // the old type has been CardSetBitMap. - if (card_set_type(source_card_set) != CardSetBitMap) { - // We only need to transfer from anything below CardSetBitMap. + // the old type has been ContainerBitMap. + if (container_type(source_container) != ContainerBitMap) { + // We only need to transfer from anything below ContainerBitMap. G1TransferCard iter(this, card_region); - iterate_cards_during_transfer(source_card_set, iter); + iterate_cards_during_transfer(source_container, iter); } else { - uint diff = _config->max_cards_in_howl_bitmap() - card_set_ptr(source_card_set)->num_bits_set(); + uint diff = _config->max_cards_in_howl_bitmap() - container_ptr(source_container)->num_bits_set(); // Need to correct for that the Full remembered set occupies more cards than the // bitmap before. @@ -635,10 +621,10 @@ void G1CardSet::transfer_cards_in_howl(CardSetPtr parent_card_set, // G1CardSet::add_to_howl after coarsening. diff -= 1; - G1CardSetHowl* howling_array = card_set_ptr(parent_card_set); + G1CardSetHowl* howling_array = container_ptr(parent_container); Atomic::add(&howling_array->_num_entries, diff, memory_order_relaxed); - G1CardSetHashTableValue* table_entry = get_card_set(card_region); + G1CardSetHashTableValue* table_entry = get_container(card_region); assert(table_entry != nullptr, "Table entry not found for transferred cards"); Atomic::add(&table_entry->_num_occupied, diff, memory_order_relaxed); @@ -647,72 +633,75 @@ void G1CardSet::transfer_cards_in_howl(CardSetPtr parent_card_set, } } -G1AddCardResult G1CardSet::add_to_card_set(volatile CardSetPtr* card_set_addr, CardSetPtr card_set, uint card_region, uint card_in_region, bool increment_total) { - assert(card_set_addr != nullptr, "Cannot add to empty cardset"); +G1AddCardResult G1CardSet::add_to_container(ContainerPtr volatile* container_addr, + ContainerPtr container, + uint card_region, + uint card_in_region, + bool increment_total) { + assert(container_addr != nullptr, "must be"); G1AddCardResult add_result; - switch (card_set_type(card_set)) { - case CardSetInlinePtr: { - add_result = add_to_inline_ptr(card_set_addr, card_set, card_in_region); + switch (container_type(container)) { + case ContainerInlinePtr: { + add_result = add_to_inline_ptr(container_addr, container, card_in_region); break; } - case CardSetArrayOfCards : { - add_result = add_to_array(card_set, card_in_region); + case ContainerArrayOfCards: { + add_result = add_to_array(container, card_in_region); break; } - case CardSetBitMap: { - add_result = add_to_bitmap(card_set, card_in_region); + case ContainerBitMap: { + add_result = add_to_bitmap(container, card_in_region); break; } - case CardSetHowl: { - assert(CardSetHowl == card_set_type(FullCardSet), "must be"); - if (card_set == FullCardSet) { + case ContainerHowl: { + assert(ContainerHowl == container_type(FullCardSet), "must be"); + if (container == FullCardSet) { return Found; } - add_result = add_to_howl(card_set, card_region, card_in_region, increment_total); + add_result = add_to_howl(container, card_region, card_in_region, increment_total); break; } default: ShouldNotReachHere(); } - return add_result; } -G1CardSetHashTableValue* G1CardSet::get_or_add_card_set(uint card_region, bool* should_grow_table) { +G1CardSetHashTableValue* G1CardSet::get_or_add_container(uint card_region, bool* should_grow_table) { return _table->get_or_add(card_region, should_grow_table); } -G1CardSetHashTableValue* G1CardSet::get_card_set(uint card_region) { +G1CardSetHashTableValue* G1CardSet::get_container(uint card_region) { return _table->get(card_region); } G1AddCardResult G1CardSet::add_card(uint card_region, uint card_in_region, bool increment_total) { G1AddCardResult add_result; - CardSetPtr to_transfer = nullptr; - CardSetPtr card_set; + ContainerPtr to_transfer = nullptr; + ContainerPtr container; bool should_grow_table = false; - G1CardSetHashTableValue* table_entry = get_or_add_card_set(card_region, &should_grow_table); + G1CardSetHashTableValue* table_entry = get_or_add_container(card_region, &should_grow_table); while (true) { - card_set = acquire_card_set(&table_entry->_card_set); - add_result = add_to_card_set(&table_entry->_card_set, card_set, card_region, card_in_region, increment_total); + container = acquire_container(&table_entry->_container); + add_result = add_to_container(&table_entry->_container, container, card_region, card_in_region, increment_total); if (add_result != Overflow) { break; } // Card set has overflown. Coarsen or retry. - bool coarsened = coarsen_card_set(&table_entry->_card_set, card_set, card_in_region); - _coarsen_stats.record_coarsening(card_set_type(card_set), !coarsened); + bool coarsened = coarsen_container(&table_entry->_container, container, card_in_region); + _coarsen_stats.record_coarsening(container_type(container), !coarsened); if (coarsened) { - // We have been the one coarsening this card set (and in the process added that card). + // We successful coarsened this card set container (and in the process added the card). add_result = Added; - to_transfer = card_set; + to_transfer = container; break; } // Somebody else beat us to coarsening. Retry. - release_and_maybe_free_card_set(card_set); + release_and_maybe_free_container(container); } if (increment_total && add_result == Added) { @@ -726,7 +715,7 @@ G1AddCardResult G1CardSet::add_card(uint card_region, uint card_in_region, bool transfer_cards(table_entry, to_transfer, card_region); } - release_and_maybe_free_card_set(card_set); + release_and_maybe_free_container(container); return add_result; } @@ -735,29 +724,29 @@ bool G1CardSet::contains_card(uint card_region, uint card_in_region) { assert(card_in_region < _config->max_cards_in_region(), "Card %u is beyond max %u", card_in_region, _config->max_cards_in_region()); - // Protect the card set from reclamation. + // Protect the card set container from reclamation. GlobalCounter::CriticalSection cs(Thread::current()); - G1CardSetHashTableValue* table_entry = get_card_set(card_region); + G1CardSetHashTableValue* table_entry = get_container(card_region); if (table_entry == nullptr) { return false; } - CardSetPtr card_set = table_entry->_card_set; - if (card_set == FullCardSet) { + ContainerPtr container = table_entry->_container; + if (container == FullCardSet) { // contains_card() is not a performance critical method so we do not hide that // case in the switch below. return true; } - switch (card_set_type(card_set)) { - case CardSetInlinePtr: { - G1CardSetInlinePtr ptr(card_set); + switch (container_type(container)) { + case ContainerInlinePtr: { + G1CardSetInlinePtr ptr(container); return ptr.contains(card_in_region, _config->inline_ptr_bits_per_card()); } - case CardSetArrayOfCards : return card_set_ptr(card_set)->contains(card_in_region); - case CardSetBitMap: return card_set_ptr(card_set)->contains(card_in_region, _config->max_cards_in_howl_bitmap()); - case CardSetHowl: { - G1CardSetHowl* howling_array = card_set_ptr(card_set); + case ContainerArrayOfCards: return container_ptr(container)->contains(card_in_region); + case ContainerBitMap: return container_ptr(container)->contains(card_in_region, _config->max_cards_in_howl_bitmap()); + case ContainerHowl: { + G1CardSetHowl* howling_array = container_ptr(container); return howling_array->contains(card_in_region, _config); } @@ -767,53 +756,53 @@ bool G1CardSet::contains_card(uint card_region, uint card_in_region) { } void G1CardSet::print_info(outputStream* st, uint card_region, uint card_in_region) { - G1CardSetHashTableValue* table_entry = get_card_set(card_region); + G1CardSetHashTableValue* table_entry = get_container(card_region); if (table_entry == nullptr) { st->print("NULL card set"); return; } - CardSetPtr card_set = table_entry->_card_set; - if (card_set == FullCardSet) { + ContainerPtr container = table_entry->_container; + if (container == FullCardSet) { st->print("FULL card set)"); return; } - switch (card_set_type(card_set)) { - case CardSetInlinePtr: { + switch (container_type(container)) { + case ContainerInlinePtr: { st->print("InlinePtr not containing %u", card_in_region); break; } - case CardSetArrayOfCards : { + case ContainerArrayOfCards: { st->print("AoC not containing %u", card_in_region); break; } - case CardSetBitMap: { + case ContainerBitMap: { st->print("BitMap not containing %u", card_in_region); break; } - case CardSetHowl: { - st->print("CardSetHowl not containing %u", card_in_region); + case ContainerHowl: { + st->print("ContainerHowl not containing %u", card_in_region); break; } - default: st->print("Unknown card set type %u", card_set_type(card_set)); ShouldNotReachHere(); break; + default: st->print("Unknown card set container type %u", container_type(container)); ShouldNotReachHere(); break; } } template -void G1CardSet::iterate_cards_during_transfer(CardSetPtr const card_set, CardVisitor& cl) { - uint type = card_set_type(card_set); - assert(type == CardSetInlinePtr || type == CardSetArrayOfCards, +void G1CardSet::iterate_cards_during_transfer(ContainerPtr const container, CardVisitor& cl) { + uint type = container_type(container); + assert(type == ContainerInlinePtr || type == ContainerArrayOfCards, "invalid card set type %d to transfer from", - card_set_type(card_set)); + container_type(container)); switch (type) { - case CardSetInlinePtr: { - G1CardSetInlinePtr ptr(card_set); + case ContainerInlinePtr: { + G1CardSetInlinePtr ptr(container); ptr.iterate(cl, _config->inline_ptr_bits_per_card()); return; } - case CardSetArrayOfCards : { - card_set_ptr(card_set)->iterate(cl); + case ContainerArrayOfCards: { + container_ptr(container)->iterate(cl); return; } default: @@ -821,7 +810,7 @@ void G1CardSet::iterate_cards_during_transfer(CardSetPtr const card_set, CardVis } } -void G1CardSet::iterate_containers(CardSetPtrClosure* cl, bool at_safepoint) { +void G1CardSet::iterate_containers(ContainerPtrClosure* cl, bool at_safepoint) { if (at_safepoint) { _table->iterate_safepoint(cl); } else { @@ -852,7 +841,7 @@ public: }; template class CardOrRanges> -class G1CardSetContainersClosure : public G1CardSet::CardSetPtrClosure { +class G1CardSetContainersClosure : public G1CardSet::ContainerPtrClosure { G1CardSet* _card_set; Closure& _cl; @@ -863,9 +852,9 @@ public: _card_set(card_set), _cl(cl) { } - void do_cardsetptr(uint region_idx, size_t num_occupied, G1CardSet::CardSetPtr card_set) override { + void do_containerptr(uint region_idx, size_t num_occupied, G1CardSet::ContainerPtr container) override { CardOrRanges cl(_cl, region_idx); - _card_set->iterate_cards_or_ranges_in_container(card_set, cl); + _card_set->iterate_cards_or_ranges_in_container(container, cl); } }; @@ -887,13 +876,13 @@ size_t G1CardSet::occupied() const { } size_t G1CardSet::num_containers() { - class GetNumberOfContainers : public CardSetPtrClosure { + class GetNumberOfContainers : public ContainerPtrClosure { public: size_t _count; - GetNumberOfContainers() : CardSetPtrClosure(), _count(0) { } + GetNumberOfContainers() : ContainerPtrClosure(), _count(0) { } - void do_cardsetptr(uint region_idx, size_t num_occupied, CardSetPtr card_set) override { + void do_containerptr(uint region_idx, size_t num_occupied, ContainerPtr container) override { _count++; } } cl; diff --git a/src/hotspot/share/gc/g1/g1CardSet.hpp b/src/hotspot/share/gc/g1/g1CardSet.hpp index 465984d713873d76bb52e42928534b0c364eb39c..946d8cb73382b954ecf23d23124c909edc3e477f 100644 --- a/src/hotspot/share/gc/g1/g1CardSet.hpp +++ b/src/hotspot/share/gc/g1/g1CardSet.hpp @@ -26,10 +26,7 @@ #define SHARE_GC_G1_G1CARDSET_HPP #include "memory/allocation.hpp" -#include "memory/padded.hpp" -#include "oops/oopsHierarchy.hpp" #include "utilities/concurrentHashTable.hpp" -#include "utilities/lockFreeStack.hpp" class G1CardSetAllocOptions; class G1CardSetHashTable; @@ -147,10 +144,10 @@ public: class G1CardSetCoarsenStats { public: // Number of entries in the statistics tables: since we index with the source - // cardset of the coarsening, this is the total number of combinations of - // card sets - 1. + // container of the coarsening, this is the total number of combinations of + // card set containers - 1. static constexpr size_t NumCoarsenCategories = 7; - // Coarsening statistics for the possible CardSetPtr in the Howl card set + // Coarsening statistics for the possible ContainerPtr in the Howl card set // start from this offset. static constexpr size_t CoarsenHowlOffset = 4; @@ -173,14 +170,14 @@ public: void print_on(outputStream* out); }; -// Sparse set of card indexes comprising a remembered set on the Java heap. Card +// Set of card indexes comprising a remembered set on the Java heap. Card // size is assumed to be card table card size. // // Technically it is implemented using a ConcurrentHashTable that stores a card // set container for every region containing at least one card. // // There are in total five different containers, encoded in the ConcurrentHashTable -// node as CardSetPtr. A CardSetPtr may cover the whole region or just a part of +// node as ContainerPtr. A ContainerPtr may cover the whole region or just a part of // it. // See its description below for more information. class G1CardSet : public CHeapObj { @@ -194,46 +191,46 @@ class G1CardSet : public CHeapObj { static G1CardSetCoarsenStats _coarsen_stats; // Coarsening statistics since VM start. static G1CardSetCoarsenStats _last_coarsen_stats; // Coarsening statistics at last GC. public: - // Two lower bits are used to encode the card storage types - static const uintptr_t CardSetPtrHeaderSize = 2; + // Two lower bits are used to encode the card set container types + static const uintptr_t ContainerPtrHeaderSize = 2; - // CardSetPtr represents the card storage type of a given covered area. It encodes - // a type in the LSBs, in addition to having a few significant values. + // ContainerPtr represents the card set container type of a given covered area. + // It encodes a type in the LSBs, in addition to having a few significant values. // // Possible encodings: // // 0...00000 free (Empty, should never happen) - // 1...11111 full All card indexes in the whole area this CardSetPtr covers are part of this container. - // X...XXX00 inline-ptr-cards A handful of card indexes covered by this CardSetPtr are encoded within the CardSetPtr. + // 1...11111 full All card indexes in the whole area this ContainerPtr covers are part of this container. + // X...XXX00 inline-ptr-cards A handful of card indexes covered by this ContainerPtr are encoded within the ContainerPtr. // X...XXX01 array of cards The container is a contiguous array of card indexes. // X...XXX10 bitmap The container uses a bitmap to determine whether a given index is part of this set. - // X...XXX11 howl This is a card set container containing an array of CardSetPtr, with each CardSetPtr + // X...XXX11 howl This is a card set container containing an array of ContainerPtr, with each ContainerPtr // limited to a sub-range of the original range. Currently only one level of this // container is supported. - typedef void* CardSetPtr; + using ContainerPtr = void*; // Coarsening happens in the order below: - // CardSetInlinePtr -> CardSetArrayOfCards -> CardSetHowl -> Full - // Corsening of containers inside the CardSetHowl happens in the order: - // CardSetInlinePtr -> CardSetArrayOfCards -> CardSetBitMap -> Full - static const uintptr_t CardSetInlinePtr = 0x0; - static const uintptr_t CardSetArrayOfCards = 0x1; - static const uintptr_t CardSetBitMap = 0x2; - static const uintptr_t CardSetHowl = 0x3; + // ContainerInlinePtr -> ContainerArrayOfCards -> ContainerHowl -> Full + // Corsening of containers inside the ContainerHowl happens in the order: + // ContainerInlinePtr -> ContainerArrayOfCards -> ContainerBitMap -> Full + static const uintptr_t ContainerInlinePtr = 0x0; + static const uintptr_t ContainerArrayOfCards = 0x1; + static const uintptr_t ContainerBitMap = 0x2; + static const uintptr_t ContainerHowl = 0x3; // The special sentinel values - static constexpr CardSetPtr FreeCardSet = nullptr; - // Unfortunately we can't make (G1CardSet::CardSetPtr)-1 constexpr because + static constexpr ContainerPtr FreeCardSet = nullptr; + // Unfortunately we can't make (G1CardSet::ContainerPtr)-1 constexpr because // reinterpret_casts are forbidden in constexprs. Use a regular static instead. - static CardSetPtr FullCardSet; + static ContainerPtr FullCardSet; - static const uintptr_t CardSetPtrTypeMask = ((uintptr_t)1 << CardSetPtrHeaderSize) - 1; + static const uintptr_t ContainerPtrTypeMask = ((uintptr_t)1 << ContainerPtrHeaderSize) - 1; - static CardSetPtr strip_card_set_type(CardSetPtr ptr) { return (CardSetPtr)((uintptr_t)ptr & ~CardSetPtrTypeMask); } + static ContainerPtr strip_container_type(ContainerPtr ptr) { return (ContainerPtr)((uintptr_t)ptr & ~ContainerPtrTypeMask); } - static uint card_set_type(CardSetPtr ptr) { return (uintptr_t)ptr & CardSetPtrTypeMask; } + static uint container_type(ContainerPtr ptr) { return (uintptr_t)ptr & ContainerPtrTypeMask; } template - static T* card_set_ptr(CardSetPtr ptr); + static T* container_ptr(ContainerPtr ptr); private: G1CardSetMemoryManager* _mm; @@ -245,42 +242,42 @@ private: // be (slightly) more cards in the card set than this value in reality. size_t _num_occupied; - CardSetPtr make_card_set_ptr(void* value, uintptr_t type); + ContainerPtr make_container_ptr(void* value, uintptr_t type); - CardSetPtr acquire_card_set(CardSetPtr volatile* card_set_addr); - // Returns true if the card set should be released - bool release_card_set(CardSetPtr card_set); + ContainerPtr acquire_container(ContainerPtr volatile* container_addr); + // Returns true if the card set container should be released + bool release_container(ContainerPtr container); // Release card set and free if needed. - void release_and_maybe_free_card_set(CardSetPtr card_set); + void release_and_maybe_free_container(ContainerPtr container); // Release card set and free (and it must be freeable). - void release_and_must_free_card_set(CardSetPtr card_set); + void release_and_must_free_container(ContainerPtr container); - // Coarsens the CardSet cur_card_set to the next level; tries to replace the - // previous CardSet with a new one which includes the given card_in_region. - // coarsen_card_set does not transfer cards from cur_card_set - // to the new card_set. Transfer is achieved by transfer_cards. - // Returns true if this was the thread that coarsened the CardSet (and added the card). - bool coarsen_card_set(CardSetPtr volatile* card_set_addr, - CardSetPtr cur_card_set, - uint card_in_region, bool within_howl = false); + // Coarsens the card set container cur_container to the next level; tries to replace the + // previous ContainerPtr with a new one which includes the given card_in_region. + // coarsen_container does not transfer cards from cur_container + // to the new container. Transfer is achieved by transfer_cards. + // Returns true if this was the thread that coarsened the container (and added the card). + bool coarsen_container(ContainerPtr volatile* container_addr, + ContainerPtr cur_container, + uint card_in_region, bool within_howl = false); - CardSetPtr create_coarsened_array_of_cards(uint card_in_region, bool within_howl); + ContainerPtr create_coarsened_array_of_cards(uint card_in_region, bool within_howl); // Transfer entries from source_card_set to a recently installed coarser storage type - // We only need to transfer anything finer than CardSetBitMap. "Full" contains + // We only need to transfer anything finer than ContainerBitMap. "Full" contains // all elements anyway. - void transfer_cards(G1CardSetHashTableValue* table_entry, CardSetPtr source_card_set, uint card_region); - void transfer_cards_in_howl(CardSetPtr parent_card_set, CardSetPtr source_card_set, uint card_region); + void transfer_cards(G1CardSetHashTableValue* table_entry, ContainerPtr source_container, uint card_region); + void transfer_cards_in_howl(ContainerPtr parent_container, ContainerPtr source_container, uint card_region); - G1AddCardResult add_to_card_set(CardSetPtr volatile* card_set_addr, CardSetPtr card_set, uint card_region, uint card, bool increment_total = true); + G1AddCardResult add_to_container(ContainerPtr volatile* container_addr, ContainerPtr container, uint card_region, uint card, bool increment_total = true); - G1AddCardResult add_to_inline_ptr(CardSetPtr volatile* card_set_addr, CardSetPtr card_set, uint card_in_region); - G1AddCardResult add_to_array(CardSetPtr card_set, uint card_in_region); - G1AddCardResult add_to_bitmap(CardSetPtr card_set, uint card_in_region); - G1AddCardResult add_to_howl(CardSetPtr parent_card_set, uint card_region, uint card_in_region, bool increment_total = true); + G1AddCardResult add_to_inline_ptr(ContainerPtr volatile* container_addr, ContainerPtr container, uint card_in_region); + G1AddCardResult add_to_array(ContainerPtr container, uint card_in_region); + G1AddCardResult add_to_bitmap(ContainerPtr container, uint card_in_region); + G1AddCardResult add_to_howl(ContainerPtr parent_container, uint card_region, uint card_in_region, bool increment_total = true); - G1CardSetHashTableValue* get_or_add_card_set(uint card_region, bool* should_grow_table); - G1CardSetHashTableValue* get_card_set(uint card_region); + G1CardSetHashTableValue* get_or_add_container(uint card_region, bool* should_grow_table); + G1CardSetHashTableValue* get_container(uint card_region); // Iterate over cards of a card set container during transfer of the cards from // one container to another. Executes @@ -289,11 +286,11 @@ private: // // on the given class. template - void iterate_cards_during_transfer(CardSetPtr const card_set, CardVisitor& vl); + void iterate_cards_during_transfer(ContainerPtr const container, CardVisitor& vl); - uint card_set_type_to_mem_object_type(uintptr_t type) const; + uint container_type_to_mem_object_type(uintptr_t type) const; uint8_t* allocate_mem_object(uintptr_t type); - void free_mem_object(CardSetPtr card_set); + void free_mem_object(ContainerPtr container); public: G1CardSetConfiguration* config() const { return _config; } @@ -302,8 +299,8 @@ public: G1CardSet(G1CardSetConfiguration* config, G1CardSetMemoryManager* mm); virtual ~G1CardSet(); - // Adds the given card to this set, returning an appropriate result. If added, - // updates the total count. + // Adds the given card to this set, returning an appropriate result. + // If incremental_count is true and the card has been added, updates the total count. G1AddCardResult add_card(uint card_region, uint card_in_region, bool increment_total = true); bool contains_card(uint card_region, uint card_in_region); @@ -351,14 +348,14 @@ public: // start_iterate(). // template - void iterate_cards_or_ranges_in_container(CardSetPtr const card_set, CardOrRangeVisitor& cl); + void iterate_cards_or_ranges_in_container(ContainerPtr const container, CardOrRangeVisitor& cl); - class CardSetPtrClosure { + class ContainerPtrClosure { public: - virtual void do_cardsetptr(uint region_idx, size_t num_occupied, CardSetPtr card_set) = 0; + virtual void do_containerptr(uint region_idx, size_t num_occupied, ContainerPtr container) = 0; }; - void iterate_containers(CardSetPtrClosure* cl, bool safepoint = false); + void iterate_containers(ContainerPtrClosure* cl, bool safepoint = false); class CardClosure { public: @@ -370,13 +367,13 @@ public: class G1CardSetHashTableValue { public: - using CardSetPtr = G1CardSet::CardSetPtr; + using ContainerPtr = G1CardSet::ContainerPtr; const uint _region_idx; uint volatile _num_occupied; - CardSetPtr volatile _card_set; + ContainerPtr volatile _container; - G1CardSetHashTableValue(uint region_idx, CardSetPtr card_set) : _region_idx(region_idx), _num_occupied(0), _card_set(card_set) { } + G1CardSetHashTableValue(uint region_idx, ContainerPtr container) : _region_idx(region_idx), _num_occupied(0), _container(container) { } }; class G1CardSetHashTableConfig : public StackObj { @@ -391,6 +388,6 @@ public: static void free_node(void* context, void* memory, Value const& value); }; -typedef ConcurrentHashTable CardSetHash; +using CardSetHash = ConcurrentHashTable; #endif // SHARE_GC_G1_G1CARDSET_HPP diff --git a/src/hotspot/share/gc/g1/g1CardSet.inline.hpp b/src/hotspot/share/gc/g1/g1CardSet.inline.hpp index 99938b4b74eb55313e244ecfebe5b07806dd9c55..49d7928735a300f577aa4cdc6c85b30d843de5a5 100644 --- a/src/hotspot/share/gc/g1/g1CardSet.inline.hpp +++ b/src/hotspot/share/gc/g1/g1CardSet.inline.hpp @@ -28,55 +28,54 @@ #include "gc/g1/g1CardSet.hpp" #include "gc/g1/g1CardSetContainers.inline.hpp" #include "gc/g1/g1GCPhaseTimes.hpp" -#include "runtime/atomic.hpp" #include "logging/log.hpp" template -inline T* G1CardSet::card_set_ptr(CardSetPtr ptr) { - return (T*)strip_card_set_type(ptr); +inline T* G1CardSet::container_ptr(ContainerPtr ptr) { + return (T*)strip_container_type(ptr); } -inline G1CardSet::CardSetPtr G1CardSet::make_card_set_ptr(void* value, uintptr_t type) { - assert(card_set_type(value) == 0, "Given ptr " PTR_FORMAT " already has type bits set", p2i(value)); - return (CardSetPtr)((uintptr_t)value | type); +inline G1CardSet::ContainerPtr G1CardSet::make_container_ptr(void* value, uintptr_t type) { + assert(container_type(value) == 0, "Given ptr " PTR_FORMAT " already has type bits set", p2i(value)); + return (ContainerPtr)((uintptr_t)value | type); } template -inline void G1CardSet::iterate_cards_or_ranges_in_container(CardSetPtr const card_set, CardOrRangeVisitor& cl) { - switch (card_set_type(card_set)) { - case CardSetInlinePtr: { +inline void G1CardSet::iterate_cards_or_ranges_in_container(ContainerPtr const container, CardOrRangeVisitor& cl) { + switch (container_type(container)) { + case ContainerInlinePtr: { if (cl.start_iterate(G1GCPhaseTimes::MergeRSMergedInline)) { - G1CardSetInlinePtr ptr(card_set); + G1CardSetInlinePtr ptr(container); ptr.iterate(cl, _config->inline_ptr_bits_per_card()); } return; } - case CardSetArrayOfCards : { + case ContainerArrayOfCards: { if (cl.start_iterate(G1GCPhaseTimes::MergeRSMergedArrayOfCards)) { - card_set_ptr(card_set)->iterate(cl); + container_ptr(container)->iterate(cl); } return; } - case CardSetBitMap: { + case ContainerBitMap: { // There is no first-level bitmap spanning the whole area. ShouldNotReachHere(); return; } - case CardSetHowl: { - assert(card_set_type(FullCardSet) == CardSetHowl, "Must be"); - if (card_set == FullCardSet) { + case ContainerHowl: { + assert(container_type(FullCardSet) == ContainerHowl, "Must be"); + if (container == FullCardSet) { if (cl.start_iterate(G1GCPhaseTimes::MergeRSMergedFull)) { cl(0, _config->max_cards_in_region()); } return; } if (cl.start_iterate(G1GCPhaseTimes::MergeRSMergedHowl)) { - card_set_ptr(card_set)->iterate(cl, _config); + container_ptr(container)->iterate(cl, _config); } return; } } - log_error(gc)("Unkown card set type %u", card_set_type(card_set)); + log_error(gc)("Unkown card set container type %u", container_type(container)); ShouldNotReachHere(); } diff --git a/src/hotspot/share/gc/g1/g1CardSetContainers.hpp b/src/hotspot/share/gc/g1/g1CardSetContainers.hpp index b74a68c84ae225644af4ee64f0b051843694cb0b..453594da3f9e570d0ad7da90999cd5bb544c14e7 100644 --- a/src/hotspot/share/gc/g1/g1CardSetContainers.hpp +++ b/src/hotspot/share/gc/g1/g1CardSetContainers.hpp @@ -28,15 +28,10 @@ #include "gc/g1/g1CardSet.hpp" #include "memory/allocation.hpp" #include "runtime/atomic.hpp" -#include "utilities/bitMap.inline.hpp" +#include "utilities/bitMap.hpp" #include "utilities/globalDefinitions.hpp" -#include "utilities/spinYield.hpp" -#include "logging/log.hpp" - -#include "runtime/thread.inline.hpp" - -// A helper class to encode a few card indexes within a CardSetPtr. +// A helper class to encode a few card indexes within a ContainerPtr. // // The pointer value (either 32 or 64 bits) is split into two areas: // @@ -70,16 +65,16 @@ class G1CardSetInlinePtr : public StackObj { friend class G1CardSetContainersTest; - typedef G1CardSet::CardSetPtr CardSetPtr; + using ContainerPtr = G1CardSet::ContainerPtr; - CardSetPtr volatile * _value_addr; - CardSetPtr _value; + ContainerPtr volatile * _value_addr; + ContainerPtr _value; static const uint SizeFieldLen = 3; static const uint SizeFieldPos = 2; - static const uint HeaderSize = G1CardSet::CardSetPtrHeaderSize + SizeFieldLen; + static const uint HeaderSize = G1CardSet::ContainerPtrHeaderSize + SizeFieldLen; - static const uint BitsInValue = sizeof(CardSetPtr) * BitsPerByte; + static const uint BitsInValue = sizeof(ContainerPtr) * BitsPerByte; static const uintptr_t SizeFieldMask = (((uint)1 << SizeFieldLen) - 1) << SizeFieldPos; @@ -87,9 +82,9 @@ class G1CardSetInlinePtr : public StackObj { return (idx * bits_per_card + HeaderSize); } - static CardSetPtr merge(CardSetPtr orig_value, uint card_in_region, uint idx, uint bits_per_card); + static ContainerPtr merge(ContainerPtr orig_value, uint card_in_region, uint idx, uint bits_per_card); - static uint card_at(CardSetPtr value, uint const idx, uint const bits_per_card) { + static uint card_at(ContainerPtr value, uint const idx, uint const bits_per_card) { uint8_t card_pos = card_pos_for(idx, bits_per_card); uint result = ((uintptr_t)value >> card_pos) & (((uintptr_t)1 << bits_per_card) - 1); return result; @@ -98,14 +93,14 @@ class G1CardSetInlinePtr : public StackObj { uint find(uint const card_idx, uint const bits_per_card, uint start_at, uint num_cards); public: - G1CardSetInlinePtr() : _value_addr(nullptr), _value((CardSetPtr)G1CardSet::CardSetInlinePtr) { } + G1CardSetInlinePtr() : _value_addr(nullptr), _value((ContainerPtr)G1CardSet::ContainerInlinePtr) { } - G1CardSetInlinePtr(CardSetPtr value) : _value_addr(nullptr), _value(value) { - assert(G1CardSet::card_set_type(_value) == G1CardSet::CardSetInlinePtr, "Value " PTR_FORMAT " is not a valid G1CardSetInPtr.", p2i(_value)); + G1CardSetInlinePtr(ContainerPtr value) : _value_addr(nullptr), _value(value) { + assert(G1CardSet::container_type(_value) == G1CardSet::ContainerInlinePtr, "Value " PTR_FORMAT " is not a valid G1CardSetInlinePtr.", p2i(_value)); } - G1CardSetInlinePtr(CardSetPtr volatile* value_addr, CardSetPtr value) : _value_addr(value_addr), _value(value) { - assert(G1CardSet::card_set_type(_value) == G1CardSet::CardSetInlinePtr, "Value " PTR_FORMAT " is not a valid G1CardSetInPtr.", p2i(_value)); + G1CardSetInlinePtr(ContainerPtr volatile* value_addr, ContainerPtr value) : _value_addr(value_addr), _value(value) { + assert(G1CardSet::container_type(_value) == G1CardSet::ContainerInlinePtr, "Value " PTR_FORMAT " is not a valid G1CardSetInlinePtr.", p2i(_value)); } G1AddCardResult add(uint const card_idx, uint const bits_per_card, uint const max_cards_in_inline_ptr); @@ -115,13 +110,13 @@ public: template void iterate(CardVisitor& found, uint const bits_per_card); - operator CardSetPtr () { return _value; } + operator ContainerPtr () { return _value; } static uint max_cards_in_inline_ptr(uint bits_per_card) { return (BitsInValue - HeaderSize) / bits_per_card; } - static uint num_cards_in(CardSetPtr value) { + static uint num_cards_in(ContainerPtr value) { return ((uintptr_t)value & SizeFieldMask) >> SizeFieldPos; } }; @@ -143,18 +138,12 @@ public: // To maintain these constraints, live objects should have ((_ref_count & 0x1) == 1), // which requires that we increment the reference counts by 2 starting at _ref_count = 3. // -// When such an object is on a free list, we reuse the same field for linking -// together those free objects. -// // All but inline pointers are of this kind. For those, card entries are stored -// directly in the CardSetPtr of the ConcurrentHashTable node. +// directly in the ContainerPtr of the ConcurrentHashTable node. class G1CardSetContainer { -private: - union { - G1CardSetContainer* _next; - uintptr_t _ref_count; - }; - + uintptr_t _ref_count; +protected: + ~G1CardSetContainer() = default; public: G1CardSetContainer() : _ref_count(3) { } @@ -166,18 +155,6 @@ public: // to check the value after attempting to decrement. uintptr_t decrement_refcount(); - G1CardSetContainer* next() { - return _next; - } - - G1CardSetContainer** next_addr() { - return &_next; - } - - void set_next(G1CardSetContainer* next) { - _next = next; - } - // Log of largest card index that can be stored in any G1CardSetContainer static uint LogCardsPerRegionLimit; }; @@ -186,7 +163,7 @@ class G1CardSetArray : public G1CardSetContainer { public: typedef uint16_t EntryDataType; typedef uint EntryCountType; - using CardSetPtr = G1CardSet::CardSetPtr; + using ContainerPtr = G1CardSet::ContainerPtr; private: EntryCountType _size; EntryCountType volatile _num_entries; @@ -240,7 +217,7 @@ class G1CardSetBitMap : public G1CardSetContainer { size_t _num_bits_set; BitMap::bm_word_t _bits[1]; - using CardSetPtr = G1CardSet::CardSetPtr; + using ContainerPtr = G1CardSet::ContainerPtr; template static size_t header_size_in_bytes_internal() { @@ -275,10 +252,10 @@ public: class G1CardSetHowl : public G1CardSetContainer { public: typedef uint EntryCountType; - using CardSetPtr = G1CardSet::CardSetPtr; + using ContainerPtr = G1CardSet::ContainerPtr; EntryCountType volatile _num_entries; private: - CardSetPtr _buckets[2]; + ContainerPtr _buckets[2]; // Do not add class member variables beyond this point template @@ -286,32 +263,32 @@ private: return offset_of(Derived, _buckets); } - // Iterates over the given CardSetPtr with at index in this Howl card set, + // Iterates over the given ContainerPtr with at index in this Howl card set, // applying a CardOrRangeVisitor on it. template - void iterate_cardset(CardSetPtr const card_set, uint index, CardOrRangeVisitor& found, G1CardSetConfiguration* config); + void iterate_cardset(ContainerPtr const container, uint index, CardOrRangeVisitor& found, G1CardSetConfiguration* config); public: G1CardSetHowl(EntryCountType card_in_region, G1CardSetConfiguration* config); - CardSetPtr* get_card_set_addr(EntryCountType index) { + ContainerPtr* get_container_addr(EntryCountType index) { return &_buckets[index]; } bool contains(uint card_idx, G1CardSetConfiguration* config); - // Iterates over all CardSetPtrs in this Howl card set, applying a CardOrRangeVisitor + // Iterates over all ContainerPtrs in this Howl card set, applying a CardOrRangeVisitor // on it. template void iterate(CardOrRangeVisitor& found, G1CardSetConfiguration* config); - // Iterates over all CardSetPtrs in this Howl card set. Calls + // Iterates over all ContainerPtrs in this Howl card set. Calls // - // void operator ()(CardSetPtr* card_set_addr); + // void operator ()(ContainerPtr* card_set_addr); // // on all of them. - template - void iterate(CardSetPtrVisitor& found, uint num_card_sets); + template + void iterate(ContainerPtrVisitor& found, uint num_card_sets); static EntryCountType num_buckets(size_t size_in_bits, size_t num_cards_in_array, size_t max_buckets); @@ -323,7 +300,7 @@ public: static size_t header_size_in_bytes() { return header_size_in_bytes_internal(); } static size_t size_in_bytes(size_t num_arrays) { - return header_size_in_bytes() + sizeof(CardSetPtr) * num_arrays; + return header_size_in_bytes() + sizeof(ContainerPtr) * num_arrays; } }; diff --git a/src/hotspot/share/gc/g1/g1CardSetContainers.inline.hpp b/src/hotspot/share/gc/g1/g1CardSetContainers.inline.hpp index df0e43f0d84fc44bd211f22ebcfadb3117bb00fe..3949687a97c2fefabd10abefe252d284564844d4 100644 --- a/src/hotspot/share/gc/g1/g1CardSetContainers.inline.hpp +++ b/src/hotspot/share/gc/g1/g1CardSetContainers.inline.hpp @@ -27,9 +27,11 @@ #include "gc/g1/g1CardSetContainers.hpp" #include "gc/g1/g1GCPhaseTimes.hpp" +#include "utilities/bitMap.inline.hpp" #include "utilities/globalDefinitions.hpp" +#include "utilities/spinYield.hpp" -inline G1CardSetInlinePtr::CardSetPtr G1CardSetInlinePtr::merge(CardSetPtr orig_value, uint card_in_region, uint idx, uint bits_per_card) { +inline G1CardSetInlinePtr::ContainerPtr G1CardSetInlinePtr::merge(ContainerPtr orig_value, uint card_in_region, uint idx, uint bits_per_card) { assert((idx & (SizeFieldMask >> SizeFieldPos)) == idx, "Index %u too large to fit into size field", idx); assert(card_in_region < ((uint)1 << bits_per_card), "Card %u too large to fit into card value field", card_in_region); @@ -42,7 +44,7 @@ inline G1CardSetInlinePtr::CardSetPtr G1CardSetInlinePtr::merge(CardSetPtr orig_ uintptr_t value = ((uintptr_t)(idx + 1) << SizeFieldPos) | ((uintptr_t)card_in_region << card_pos); uintptr_t res = (((uintptr_t)orig_value & ~SizeFieldMask) | value); - return (CardSetPtr)res; + return (ContainerPtr)res; } inline G1AddCardResult G1CardSetInlinePtr::add(uint card_idx, uint bits_per_card, uint max_cards_in_inline_ptr) { @@ -62,8 +64,8 @@ inline G1AddCardResult G1CardSetInlinePtr::add(uint card_idx, uint bits_per_card if (num_cards >= max_cards_in_inline_ptr) { return Overflow; } - CardSetPtr new_value = merge(_value, card_idx, num_cards, bits_per_card); - CardSetPtr old_value = Atomic::cmpxchg(_value_addr, _value, new_value, memory_order_relaxed); + ContainerPtr new_value = merge(_value, card_idx, num_cards, bits_per_card); + ContainerPtr old_value = Atomic::cmpxchg(_value_addr, _value, new_value, memory_order_relaxed); if (_value == old_value) { return Added; } @@ -71,7 +73,7 @@ inline G1AddCardResult G1CardSetInlinePtr::add(uint card_idx, uint bits_per_card _value = old_value; // The value of the pointer may have changed to something different than // an inline card set. Exit then instead of overwriting. - if (G1CardSet::card_set_type(_value) != G1CardSet::CardSetInlinePtr) { + if (G1CardSet::container_type(_value) != G1CardSet::ContainerInlinePtr) { return Overflow; } } @@ -266,23 +268,23 @@ inline G1CardSetHowl::G1CardSetHowl(EntryCountType card_in_region, G1CardSetConf inline bool G1CardSetHowl::contains(uint card_idx, G1CardSetConfiguration* config) { EntryCountType bucket = config->howl_bucket_index(card_idx); - CardSetPtr* array_entry = get_card_set_addr(bucket); - CardSetPtr card_set = Atomic::load_acquire(array_entry); + ContainerPtr* array_entry = get_container_addr(bucket); + ContainerPtr container = Atomic::load_acquire(array_entry); - switch (G1CardSet::card_set_type(card_set)) { - case G1CardSet::CardSetArrayOfCards : { - return G1CardSet::card_set_ptr(card_set)->contains(card_idx); + switch (G1CardSet::container_type(container)) { + case G1CardSet::ContainerArrayOfCards: { + return G1CardSet::container_ptr(container)->contains(card_idx); } - case G1CardSet::CardSetBitMap: { + case G1CardSet::ContainerBitMap: { uint card_offset = config->howl_bitmap_offset(card_idx); - return G1CardSet::card_set_ptr(card_set)->contains(card_offset, config->max_cards_in_howl_bitmap()); + return G1CardSet::container_ptr(container)->contains(card_offset, config->max_cards_in_howl_bitmap()); } - case G1CardSet::CardSetInlinePtr: { - G1CardSetInlinePtr ptr(card_set); + case G1CardSet::ContainerInlinePtr: { + G1CardSetInlinePtr ptr(container); return ptr.contains(card_idx, config->inline_ptr_bits_per_card()); } - case G1CardSet::CardSetHowl: {// Fullcard set entry - assert(card_set == G1CardSet::FullCardSet, "Must be"); + case G1CardSet::ContainerHowl: {// Fullcard set entry + assert(container == G1CardSet::FullCardSet, "Must be"); return true; } } @@ -296,38 +298,38 @@ inline void G1CardSetHowl::iterate(CardOrRangeVisitor& found, G1CardSetConfigura } } -template -inline void G1CardSetHowl::iterate(CardSetPtrVisitor& found, uint num_card_sets) { +template +inline void G1CardSetHowl::iterate(ContainerPtrVisitor& found, uint num_card_sets) { for (uint i = 0; i < num_card_sets; ++i) { found(&_buckets[i]); } } template -inline void G1CardSetHowl::iterate_cardset(CardSetPtr const card_set, uint index, CardOrRangeVisitor& found, G1CardSetConfiguration* config) { - switch (G1CardSet::card_set_type(card_set)) { - case G1CardSet::CardSetInlinePtr: { +inline void G1CardSetHowl::iterate_cardset(ContainerPtr const container, uint index, CardOrRangeVisitor& found, G1CardSetConfiguration* config) { + switch (G1CardSet::container_type(container)) { + case G1CardSet::ContainerInlinePtr: { if (found.start_iterate(G1GCPhaseTimes::MergeRSHowlInline)) { - G1CardSetInlinePtr ptr(card_set); + G1CardSetInlinePtr ptr(container); ptr.iterate(found, config->inline_ptr_bits_per_card()); } return; } - case G1CardSet::CardSetArrayOfCards : { + case G1CardSet::ContainerArrayOfCards: { if (found.start_iterate(G1GCPhaseTimes::MergeRSHowlArrayOfCards)) { - G1CardSet::card_set_ptr(card_set)->iterate(found); + G1CardSet::container_ptr(container)->iterate(found); } return; } - case G1CardSet::CardSetBitMap: { + case G1CardSet::ContainerBitMap: { if (found.start_iterate(G1GCPhaseTimes::MergeRSHowlBitmap)) { uint offset = index << config->log2_max_cards_in_howl_bitmap(); - G1CardSet::card_set_ptr(card_set)->iterate(found, config->max_cards_in_howl_bitmap(), offset); + G1CardSet::container_ptr(container)->iterate(found, config->max_cards_in_howl_bitmap(), offset); } return; } - case G1CardSet::CardSetHowl: { // actually FullCardSet - assert(card_set == G1CardSet::FullCardSet, "Must be"); + case G1CardSet::ContainerHowl: { // actually FullCardSet + assert(container == G1CardSet::FullCardSet, "Must be"); if (found.start_iterate(G1GCPhaseTimes::MergeRSHowlFull)) { uint offset = index << config->log2_max_cards_in_howl_bitmap(); found(offset, config->max_cards_in_howl_bitmap()); diff --git a/src/hotspot/share/gc/g1/g1CardSetMemory.cpp b/src/hotspot/share/gc/g1/g1CardSetMemory.cpp index 85b4250090af3f1c1d467915274460e355d0b996..b68c50b5cb1b5ff4a6abd68e07e015ac765189ac 100644 --- a/src/hotspot/share/gc/g1/g1CardSetMemory.cpp +++ b/src/hotspot/share/gc/g1/g1CardSetMemory.cpp @@ -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 @@ -30,111 +30,61 @@ #include "runtime/atomic.hpp" #include "utilities/ostream.hpp" -template -G1CardSetAllocator::G1CardSetAllocator(const char* name, - const G1CardSetAllocOptions* alloc_options, - G1CardSetFreeList* free_segment_list) : +G1CardSetAllocator::G1CardSetAllocator(const char* name, + const G1CardSetAllocOptions* alloc_options, + G1CardSetFreeList* free_segment_list) : _segmented_array(alloc_options, free_segment_list), - _transfer_lock(false), - _free_slots_list(), - _pending_slots_list(), - _num_pending_slots(0), - _num_free_slots(0) + _free_slots_list(name, &_segmented_array) { uint slot_size = _segmented_array.slot_size(); assert(slot_size >= sizeof(G1CardSetContainer), "Slot instance size %u for allocator %s too small", slot_size, name); } -template -G1CardSetAllocator::~G1CardSetAllocator() { +G1CardSetAllocator::~G1CardSetAllocator() { drop_all(); } -template -bool G1CardSetAllocator::try_transfer_pending() { - // Attempt to claim the lock. - if (Atomic::load_acquire(&_transfer_lock) || // Skip CAS if likely to fail. - Atomic::cmpxchg(&_transfer_lock, false, true)) { - return false; - } - // Have the lock; perform the transfer. - - // Claim all the pending slots. - G1CardSetContainer* first = _pending_slots_list.pop_all(); - - if (first != nullptr) { - // Prepare to add the claimed slots, and update _num_pending_slots. - G1CardSetContainer* last = first; - Atomic::load_acquire(&_num_pending_slots); - - uint count = 1; - for (G1CardSetContainer* next = first->next(); next != nullptr; next = next->next()) { - last = next; - ++count; - } - - Atomic::sub(&_num_pending_slots, count); - - // Wait for any in-progress pops to avoid ABA for them. - GlobalCounter::write_synchronize(); - // Add synchronized slots to _free_slots_list. - // Update count first so there can be no underflow in allocate(). - Atomic::add(&_num_free_slots, count); - _free_slots_list.prepend(*first, *last); - } - Atomic::release_store(&_transfer_lock, false); - return true; -} - -template -void G1CardSetAllocator::free(Slot* slot) { +void G1CardSetAllocator::free(void* slot) { assert(slot != nullptr, "precondition"); - // Desired minimum transfer batch size. There is relatively little - // importance to the specific number. It shouldn't be too big, else - // we're wasting space when the release rate is low. If the release - // rate is high, we might accumulate more than this before being - // able to start a new transfer, but that's okay. Also note that - // the allocation rate and the release rate are going to be fairly - // similar, due to how the slots are used. - kbarret - uint const trigger_transfer = 10; - - uint pending_count = Atomic::add(&_num_pending_slots, 1u, memory_order_relaxed); - - G1CardSetContainer* container = reinterpret_cast(reinterpret_cast(slot)); + _free_slots_list.release(slot); +} - container->set_next(nullptr); - assert(container->next() == nullptr, "precondition"); +void G1CardSetAllocator::drop_all() { + _free_slots_list.reset(); + _segmented_array.drop_all(); +} - _pending_slots_list.push(*container); +size_t G1CardSetAllocator::mem_size() const { + return sizeof(*this) + + _segmented_array.num_segments() * sizeof(G1CardSetSegment) + + _segmented_array.num_available_slots() * _segmented_array.slot_size(); +} - if (pending_count > trigger_transfer) { - try_transfer_pending(); - } +size_t G1CardSetAllocator::wasted_mem_size() const { + uint num_wasted_slots = _segmented_array.num_available_slots() - + _segmented_array.num_allocated_slots() - + (uint)_free_slots_list.pending_count(); + return num_wasted_slots * _segmented_array.slot_size(); } -template -void G1CardSetAllocator::drop_all() { - _free_slots_list.pop_all(); - _pending_slots_list.pop_all(); - _num_pending_slots = 0; - _num_free_slots = 0; - _segmented_array.drop_all(); +uint G1CardSetAllocator::num_segments() const { + return _segmented_array.num_segments(); } -template -void G1CardSetAllocator::print(outputStream* os) { +void G1CardSetAllocator::print(outputStream* os) { uint num_allocated_slots = _segmented_array.num_allocated_slots(); uint num_available_slots = _segmented_array.num_available_slots(); uint highest = _segmented_array.first_array_segment() != nullptr ? _segmented_array.first_array_segment()->num_slots() : 0; uint num_segments = _segmented_array.num_segments(); + uint num_pending_slots = (uint)_free_slots_list.pending_count(); os->print("MA " PTR_FORMAT ": %u slots pending (allocated %u available %u) used %.3f highest %u segments %u size %zu ", p2i(this), - _num_pending_slots, + num_pending_slots, num_allocated_slots, num_available_slots, - percent_of(num_allocated_slots - _num_pending_slots, num_available_slots), + percent_of(num_allocated_slots - num_pending_slots, num_available_slots), highest, num_segments, mem_size()); @@ -143,13 +93,13 @@ void G1CardSetAllocator::print(outputStream* os) { G1CardSetMemoryManager::G1CardSetMemoryManager(G1CardSetConfiguration* config, G1CardSetFreePool* free_list_pool) : _config(config) { - _allocators = NEW_C_HEAP_ARRAY(G1CardSetAllocator, + _allocators = NEW_C_HEAP_ARRAY(G1CardSetAllocator, _config->num_mem_object_types(), mtGC); for (uint i = 0; i < num_mem_object_types(); i++) { - new (&_allocators[i]) G1CardSetAllocator(_config->mem_object_type_name_str(i), - _config->mem_object_alloc_options(i), - free_list_pool->free_list(i)); + new (&_allocators[i]) G1CardSetAllocator(_config->mem_object_type_name_str(i), + _config->mem_object_alloc_options(i), + free_list_pool->free_list(i)); } } @@ -167,7 +117,7 @@ G1CardSetMemoryManager::~G1CardSetMemoryManager() { void G1CardSetMemoryManager::free(uint type, void* value) { assert(type < num_mem_object_types(), "must be"); - _allocators[type].free((G1CardSetContainer*)value); + _allocators[type].free(value); } void G1CardSetMemoryManager::flush() { @@ -188,9 +138,8 @@ size_t G1CardSetMemoryManager::mem_size() const { for (uint i = 0; i < num_mem_object_types(); i++) { result += _allocators[i].mem_size(); } - return sizeof(*this) - - (sizeof(G1CardSetAllocator) * num_mem_object_types()) + - result; + return sizeof(*this) + result - + (sizeof(G1CardSetAllocator) * num_mem_object_types()); } size_t G1CardSetMemoryManager::wasted_mem_size() const { diff --git a/src/hotspot/share/gc/g1/g1CardSetMemory.hpp b/src/hotspot/share/gc/g1/g1CardSetMemory.hpp index a9d235f39e5c509bf6b041876efe37f68faa923b..c2663b41cf1ab8afb6cd9568426aeb3931930a10 100644 --- a/src/hotspot/share/gc/g1/g1CardSetMemory.hpp +++ b/src/hotspot/share/gc/g1/g1CardSetMemory.hpp @@ -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 @@ -29,9 +29,9 @@ #include "gc/g1/g1CardSetContainers.hpp" #include "gc/g1/g1SegmentedArray.hpp" #include "gc/g1/g1SegmentedArrayFreePool.hpp" +#include "gc/shared/freeListAllocator.hpp" #include "memory/allocation.hpp" #include "utilities/growableArray.hpp" -#include "utilities/lockFreeStack.hpp" class G1CardSetConfiguration; class outputStream; @@ -62,52 +62,13 @@ typedef G1SegmentedArraySegment G1CardSetSegment; typedef G1SegmentedArrayFreeList G1CardSetFreeList; -// Arena-like allocator for (card set) heap memory objects (Slot slots). +// Arena-like allocator for (card set) heap memory objects. // -// Allocation and deallocation in the first phase on G1CardSetContainer basis -// may occur by multiple threads at once. -// -// Allocation occurs from an internal free list of G1CardSetContainers first, -// only then trying to bump-allocate from the current G1CardSetSegment. If there is -// none, this class allocates a new G1CardSetSegment (allocated from the C heap, -// asking the G1CardSetAllocOptions instance about sizes etc) and uses that one. -// -// The SegmentStack free list is a linked list of G1CardSetContainers -// within all G1CardSetSegment instances allocated so far. It uses a separate -// pending list and global synchronization to avoid the ABA problem when the -// user frees a memory object. -// -// The class also manages a few counters for statistics using atomic operations. -// Their values are only consistent within each other with extra global -// synchronization. -// -// Since it is expected that every CardSet (and in extension each region) has its -// own set of allocators, there is intentionally no padding between them to save -// memory. -template +// Allocation occurs from an internal free list of objects first. If the free list is +// empty then tries to allocate from the G1SegmentedArray. class G1CardSetAllocator { - // G1CardSetSegment management. - - typedef G1SegmentedArray SegmentedArray; - // G1CardSetContainer slot management within the G1CardSetSegments allocated - // by this allocator. - static G1CardSetContainer* volatile* next_ptr(G1CardSetContainer& slot); - typedef LockFreeStack SlotStack; - - SegmentedArray _segmented_array; - volatile bool _transfer_lock; - SlotStack _free_slots_list; - SlotStack _pending_slots_list; - - volatile uint _num_pending_slots; // Number of slots in the pending list. - volatile uint _num_free_slots; // Number of slots in the free list. - - // Try to transfer slots from _pending_slots_list to _free_slots_list, with a - // synchronization delay for any in-progress pops from the _free_slots_list - // to solve ABA here. - bool try_transfer_pending(); - - uint num_free_slots() const; + G1SegmentedArray _segmented_array; + FreeListAllocator _free_slots_list; public: G1CardSetAllocator(const char* name, @@ -115,25 +76,18 @@ public: G1CardSetFreeList* free_segment_list); ~G1CardSetAllocator(); - Slot* allocate(); - void free(Slot* slot); + void* allocate(); + void free(void* slot); // Deallocate all segments to the free segment list and reset this allocator. Must // be called in a globally synchronized area. void drop_all(); - size_t mem_size() const { - return sizeof(*this) + - _segmented_array.num_segments() * sizeof(G1CardSetSegment) + _segmented_array.num_available_slots() * - _segmented_array.slot_size(); - } + size_t mem_size() const; - size_t wasted_mem_size() const { - return (_segmented_array.num_available_slots() - (_segmented_array.num_allocated_slots() - _num_pending_slots)) * - _segmented_array.slot_size(); - } + size_t wasted_mem_size() const; - inline uint num_segments() { return _segmented_array.num_segments(); } + uint num_segments() const; void print(outputStream* os); }; @@ -143,7 +97,7 @@ typedef G1SegmentedArrayFreePool G1CardSetFreePool; class G1CardSetMemoryManager : public CHeapObj { G1CardSetConfiguration* _config; - G1CardSetAllocator* _allocators; + G1CardSetAllocator* _allocators; uint num_mem_object_types() const; public: diff --git a/src/hotspot/share/gc/g1/g1CardSetMemory.inline.hpp b/src/hotspot/share/gc/g1/g1CardSetMemory.inline.hpp index 21a509f449d82d5c73f4d7844881d2180b8a35a1..bdf69e227dfc661f3af4351ce6c45a6a8218d031 100644 --- a/src/hotspot/share/gc/g1/g1CardSetMemory.inline.hpp +++ b/src/hotspot/share/gc/g1/g1CardSetMemory.inline.hpp @@ -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 @@ -26,37 +26,13 @@ #define SHARE_GC_G1_G1CARDSETMEMORY_INLINE_HPP #include "gc/g1/g1CardSetMemory.hpp" -#include "gc/g1/g1CardSetContainers.hpp" -#include "gc/g1/g1SegmentedArray.inline.hpp" -#include "utilities/ostream.hpp" - #include "gc/g1/g1CardSetContainers.inline.hpp" +#include "gc/g1/g1SegmentedArray.inline.hpp" #include "utilities/globalCounter.inline.hpp" +#include "utilities/ostream.hpp" -template -G1CardSetContainer* volatile* G1CardSetAllocator::next_ptr(G1CardSetContainer& slot) { - return slot.next_addr(); -} - -template -Slot* G1CardSetAllocator::allocate() { - assert(_segmented_array.slot_size() > 0, "instance size not set."); - - if (num_free_slots() > 0) { - // Pop under critical section to deal with ABA problem - // Other solutions to the same problem are more complicated (ref counting, HP) - GlobalCounter::CriticalSection cs(Thread::current()); - - G1CardSetContainer* container = _free_slots_list.pop(); - if (container != nullptr) { - Slot* slot = reinterpret_cast(reinterpret_cast(container)); - Atomic::sub(&_num_free_slots, 1u); - guarantee(is_aligned(slot, 8), "result " PTR_FORMAT " not aligned", p2i(slot)); - return slot; - } - } - - Slot* slot = _segmented_array.allocate(); +inline void* G1CardSetAllocator::allocate() { + void* slot = _free_slots_list.allocate(); assert(slot != nullptr, "must be"); return slot; } @@ -74,9 +50,4 @@ inline void G1CardSetMemoryManager::free_node(void* value) { free(0, value); } -template -inline uint G1CardSetAllocator::num_free_slots() const { - return Atomic::load(&_num_free_slots); -} - #endif // SHARE_GC_G1_G1CARDSETMEMORY_INLINE_HPP diff --git a/src/hotspot/share/gc/g1/g1CollectedHeap.cpp b/src/hotspot/share/gc/g1/g1CollectedHeap.cpp index cbd13a7f282e8096c44bd2de818c17a183ef1cde..3b6458b9f82b81f4131c7b80fb3953b33d0cb81a 100644 --- a/src/hotspot/share/gc/g1/g1CollectedHeap.cpp +++ b/src/hotspot/share/gc/g1/g1CollectedHeap.cpp @@ -3313,6 +3313,13 @@ HeapRegion* G1CollectedHeap::alloc_highest_free_region() { return NULL; } +void G1CollectedHeap::mark_evac_failure_object(const oop obj, uint worker_id) const { + // All objects failing evacuation are live. What we'll do is + // that we'll update the prev marking info so that they are + // all under PTAMS and explicitly marked. + _cm->par_mark_in_prev_bitmap(obj); +} + // Optimized nmethod scanning class RegisterNMethodOopClosure: public OopClosure { diff --git a/src/hotspot/share/gc/g1/g1CollectedHeap.hpp b/src/hotspot/share/gc/g1/g1CollectedHeap.hpp index 90a4dd05b217b3c814314b30c01b068cc8b51c28..de2442c7ce57588fa70feccb6129180b7bd3bd2e 100644 --- a/src/hotspot/share/gc/g1/g1CollectedHeap.hpp +++ b/src/hotspot/share/gc/g1/g1CollectedHeap.hpp @@ -28,6 +28,7 @@ #include "gc/g1/g1BarrierSet.hpp" #include "gc/g1/g1BiasedArray.hpp" #include "gc/g1/g1CardTable.hpp" +#include "gc/g1/g1CardSet.hpp" #include "gc/g1/g1CollectionSet.hpp" #include "gc/g1/g1CollectorState.hpp" #include "gc/g1/g1ConcurrentMark.hpp" @@ -1178,7 +1179,7 @@ public: size_t max_tlab_size() const override; size_t unsafe_max_tlab_alloc(Thread* ignored) const override; - inline bool is_in_young(const oop obj); + inline bool is_in_young(const oop obj) const; // Returns "true" iff the given word_size is "very large". static bool is_humongous(size_t word_size) { @@ -1248,7 +1249,7 @@ public: inline bool is_obj_dead_full(const oop obj) const; // Mark the live object that failed evacuation in the prev bitmap. - inline void mark_evac_failure_object(const oop obj, uint worker_id) const; + void mark_evac_failure_object(const oop obj, uint worker_id) const; G1ConcurrentMark* concurrent_mark() const { return _cm; } diff --git a/src/hotspot/share/gc/g1/g1CollectedHeap.inline.hpp b/src/hotspot/share/gc/g1/g1CollectedHeap.inline.hpp index 9cdf6c35432a6fcd42bc96171f012eb38e5b8654..0cd8de23e56871578153d4d58547f43def5bdb40 100644 --- a/src/hotspot/share/gc/g1/g1CollectedHeap.inline.hpp +++ b/src/hotspot/share/gc/g1/g1CollectedHeap.inline.hpp @@ -29,7 +29,6 @@ #include "gc/g1/g1BarrierSet.hpp" #include "gc/g1/g1CollectorState.hpp" -#include "gc/g1/g1ConcurrentMark.inline.hpp" #include "gc/g1/g1EvacFailureRegions.hpp" #include "gc/g1/g1Policy.hpp" #include "gc/g1/g1RemSet.hpp" @@ -208,7 +207,7 @@ void G1CollectedHeap::register_optional_region_with_region_attr(HeapRegion* r) { _region_attr.set_optional(r->hrm_index(), r->rem_set()->is_tracked()); } -inline bool G1CollectedHeap::is_in_young(const oop obj) { +inline bool G1CollectedHeap::is_in_young(const oop obj) const { if (obj == NULL) { return false; } @@ -234,13 +233,6 @@ inline bool G1CollectedHeap::is_obj_dead_full(const oop obj) const { return is_obj_dead_full(obj, heap_region_containing(obj)); } -inline void G1CollectedHeap::mark_evac_failure_object(const oop obj, uint worker_id) const { - // All objects failing evacuation are live. What we'll do is - // that we'll update the prev marking info so that they are - // all under PTAMS and explicitly marked. - _cm->par_mark_in_prev_bitmap(obj); -} - inline void G1CollectedHeap::set_humongous_reclaim_candidate(uint region, bool value) { assert(_hrm.at(region)->is_starts_humongous(), "Must start a humongous object"); _humongous_reclaim_candidates.set_candidate(region, value); diff --git a/src/hotspot/share/gc/g1/g1EvacFailureRegions.cpp b/src/hotspot/share/gc/g1/g1EvacFailureRegions.cpp index 855c549cd04800ddac3535568d84bccad96bfeb3..a67fb06a333d68d8774686c82e3742ccf9e188e2 100644 --- a/src/hotspot/share/gc/g1/g1EvacFailureRegions.cpp +++ b/src/hotspot/share/gc/g1/g1EvacFailureRegions.cpp @@ -29,6 +29,7 @@ #include "gc/g1/heapRegion.hpp" #include "memory/allocation.hpp" #include "runtime/atomic.hpp" +#include "utilities/bitMap.inline.hpp" G1EvacFailureRegions::G1EvacFailureRegions() : _regions_failed_evacuation(mtGC), diff --git a/src/hotspot/share/gc/g1/g1FullGCMarker.cpp b/src/hotspot/share/gc/g1/g1FullGCMarker.cpp index bf0b49dd8283a15ec672c863677ed86ecd6af4d2..398b904fdb2eca27caf4ac9880dc355aed13e2b9 100644 --- a/src/hotspot/share/gc/g1/g1FullGCMarker.cpp +++ b/src/hotspot/share/gc/g1/g1FullGCMarker.cpp @@ -55,7 +55,7 @@ void G1FullGCMarker::complete_marking(OopQueueSet* oop_stacks, ObjArrayTaskQueueSet* array_stacks, TaskTerminator* terminator) { do { - drain_stack(); + follow_marking_stacks(); ObjArrayTask steal_array; if (array_stacks->steal(_worker_id, steal_array)) { follow_array_chunk(objArrayOop(steal_array.obj()), steal_array.index()); diff --git a/src/hotspot/share/gc/g1/g1FullGCMarker.hpp b/src/hotspot/share/gc/g1/g1FullGCMarker.hpp index 2d935d863c5debe86f7fab6b57215ba20a2cc4a5..ee77e5044fc4bdb81b354db37e9f1598254435fe 100644 --- a/src/hotspot/share/gc/g1/g1FullGCMarker.hpp +++ b/src/hotspot/share/gc/g1/g1FullGCMarker.hpp @@ -79,12 +79,12 @@ class G1FullGCMarker : public CHeapObj { inline void follow_array(objArrayOop array); inline void follow_array_chunk(objArrayOop array, int index); - inline void drain_oop_stack(); - // Transfer contents from the objArray task queue overflow stack to the shared - // objArray stack. + inline void publish_and_drain_oop_tasks(); + // Try to publish all contents from the objArray task queue overflow stack to + // the shared objArray stack. // Returns true and a valid task if there has not been enough space in the shared - // objArray stack, otherwise the task is invalid. - inline bool transfer_objArray_overflow_stack(ObjArrayTask& task); + // objArray stack, otherwise returns false and the task is invalid. + inline bool publish_or_pop_objarray_tasks(ObjArrayTask& task); public: G1FullGCMarker(G1FullCollector* collector, @@ -103,7 +103,7 @@ public: inline void follow_klass(Klass* k); inline void follow_cld(ClassLoaderData* cld); - inline void drain_stack(); + inline void follow_marking_stacks(); void complete_marking(OopQueueSet* oop_stacks, ObjArrayTaskQueueSet* array_stacks, TaskTerminator* terminator); diff --git a/src/hotspot/share/gc/g1/g1FullGCMarker.inline.hpp b/src/hotspot/share/gc/g1/g1FullGCMarker.inline.hpp index a68bae5ced64f934b6bb7f5c22d67bc1bf81eae4..256fd766f82cf852efe477bbfae2cc2b50165044 100644 --- a/src/hotspot/share/gc/g1/g1FullGCMarker.inline.hpp +++ b/src/hotspot/share/gc/g1/g1FullGCMarker.inline.hpp @@ -151,7 +151,7 @@ inline void G1FullGCMarker::follow_object(oop obj) { } } -inline void G1FullGCMarker::drain_oop_stack() { +inline void G1FullGCMarker::publish_and_drain_oop_tasks() { oop obj; while (_oop_stack.pop_overflow(obj)) { if (!_oop_stack.try_push_to_taskqueue(obj)) { @@ -165,7 +165,7 @@ inline void G1FullGCMarker::drain_oop_stack() { } } -inline bool G1FullGCMarker::transfer_objArray_overflow_stack(ObjArrayTask& task) { +inline bool G1FullGCMarker::publish_or_pop_objarray_tasks(ObjArrayTask& task) { // It is desirable to move as much as possible work from the overflow queue to // the shared queue as quickly as possible. while (_objarray_stack.pop_overflow(task)) { @@ -176,15 +176,15 @@ inline bool G1FullGCMarker::transfer_objArray_overflow_stack(ObjArrayTask& task) return false; } -void G1FullGCMarker::drain_stack() { +void G1FullGCMarker::follow_marking_stacks() { do { // First, drain regular oop stack. - drain_oop_stack(); + publish_and_drain_oop_tasks(); // Then process ObjArrays one at a time to avoid marking stack bloat. ObjArrayTask task; - if (transfer_objArray_overflow_stack(task) || - _objarray_stack.pop_local(task)) { + if (publish_or_pop_objarray_tasks(task) || + _objarray_stack.pop_local(task)) { follow_array_chunk(objArrayOop(task.obj()), task.index()); } } while (!is_empty()); diff --git a/src/hotspot/share/gc/g1/g1FullGCOopClosures.cpp b/src/hotspot/share/gc/g1/g1FullGCOopClosures.cpp index ba3b50e5a963ee126e60b406fe232eb03dd6a8db..eebfa814ae20ae7e7fe70ddea205569db6a01968 100644 --- a/src/hotspot/share/gc/g1/g1FullGCOopClosures.cpp +++ b/src/hotspot/share/gc/g1/g1FullGCOopClosures.cpp @@ -36,7 +36,7 @@ G1IsAliveClosure::G1IsAliveClosure(G1FullCollector* collector) : G1IsAliveClosure(collector, collector->mark_bitmap()) { } -void G1FollowStackClosure::do_void() { _marker->drain_stack(); } +void G1FollowStackClosure::do_void() { _marker->follow_marking_stacks(); } void G1FullKeepAliveClosure::do_oop(oop* p) { do_oop_work(p); } void G1FullKeepAliveClosure::do_oop(narrowOop* p) { do_oop_work(p); } diff --git a/src/hotspot/share/gc/g1/g1Policy.cpp b/src/hotspot/share/gc/g1/g1Policy.cpp index d41ffcbee7b2890e5d0d73ab17fa393f07c06953..6de90942ff5a76cc57fa6ae2de616bc6bd57059c 100644 --- a/src/hotspot/share/gc/g1/g1Policy.cpp +++ b/src/hotspot/share/gc/g1/g1Policy.cpp @@ -1313,7 +1313,6 @@ void G1Policy::calculate_old_collection_set_regions(G1CollectionSetCandidates* c num_optional_regions = 0; uint num_expensive_regions = 0; - double predicted_old_time_ms = 0.0; double predicted_initial_time_ms = 0.0; double predicted_optional_time_ms = 0.0; @@ -1344,7 +1343,7 @@ void G1Policy::calculate_old_collection_set_regions(G1CollectionSetCandidates* c time_remaining_ms = MAX2(time_remaining_ms - predicted_time_ms, 0.0); // Add regions to old set until we reach the minimum amount if (num_initial_regions < min_old_cset_length) { - predicted_old_time_ms += predicted_time_ms; + predicted_initial_time_ms += predicted_time_ms; num_initial_regions++; // Record the number of regions added with no time remaining if (time_remaining_ms == 0.0) { @@ -1358,7 +1357,7 @@ void G1Policy::calculate_old_collection_set_regions(G1CollectionSetCandidates* c } else { // Keep adding regions to old set until we reach the optional threshold if (time_remaining_ms > optional_threshold_ms) { - predicted_old_time_ms += predicted_time_ms; + predicted_initial_time_ms += predicted_time_ms; num_initial_regions++; } else if (time_remaining_ms > 0) { // Keep adding optional regions until time is up. @@ -1382,7 +1381,7 @@ void G1Policy::calculate_old_collection_set_regions(G1CollectionSetCandidates* c } log_debug(gc, ergo, cset)("Finish choosing collection set old regions. Initial: %u, optional: %u, " - "predicted old time: %1.2fms, predicted optional time: %1.2fms, time remaining: %1.2f", + "predicted initial time: %1.2fms, predicted optional time: %1.2fms, time remaining: %1.2f", num_initial_regions, num_optional_regions, predicted_initial_time_ms, predicted_optional_time_ms, time_remaining_ms); } diff --git a/src/hotspot/share/gc/g1/g1SegmentedArray.hpp b/src/hotspot/share/gc/g1/g1SegmentedArray.hpp index 8091b6b2c8b4206eaeee9f5fdf3c489e8610eb9b..6c73e9855cc4ec7097e05a341e3a63f604664ebc 100644 --- a/src/hotspot/share/gc/g1/g1SegmentedArray.hpp +++ b/src/hotspot/share/gc/g1/g1SegmentedArray.hpp @@ -26,6 +26,7 @@ #ifndef SHARE_GC_G1_G1SEGMENTEDARRAY_HPP #define SHARE_GC_G1_G1SEGMENTEDARRAY_HPP +#include "gc/shared/freeListAllocator.hpp" #include "memory/allocation.hpp" #include "utilities/lockFreeStack.hpp" @@ -180,8 +181,8 @@ public: // The class also manages a few counters for statistics using atomic operations. // Their values are only consistent within each other with extra global // synchronization. -template -class G1SegmentedArray { +template +class G1SegmentedArray : public FreeListConfig { // G1SegmentedArrayAllocOptions provides parameters for allocation segment // sizing and expansion. const G1SegmentedArrayAllocOptions* _alloc_options; @@ -222,7 +223,10 @@ public: // be called in a globally synchronized area. void drop_all(); - inline Slot* allocate(); + inline void* allocate() override; + + // We do not deallocate individual slots + inline void deallocate(void* node) override { ShouldNotReachHere(); } inline uint num_segments() const; diff --git a/src/hotspot/share/gc/g1/g1SegmentedArray.inline.hpp b/src/hotspot/share/gc/g1/g1SegmentedArray.inline.hpp index 17be55fe6abeca85ff1cfbb51689f9cfffcd253a..69c3526e58d81686cd18d91495a7b4d1dc7bc95a 100644 --- a/src/hotspot/share/gc/g1/g1SegmentedArray.inline.hpp +++ b/src/hotspot/share/gc/g1/g1SegmentedArray.inline.hpp @@ -115,8 +115,8 @@ void G1SegmentedArrayFreeList::free_all() { Atomic::sub(&_mem_size, mem_size_freed, memory_order_relaxed); } -template -G1SegmentedArraySegment* G1SegmentedArray::create_new_segment(G1SegmentedArraySegment* const prev) { +template +G1SegmentedArraySegment* G1SegmentedArray::create_new_segment(G1SegmentedArraySegment* const prev) { // Take an existing segment if available. G1SegmentedArraySegment* next = _free_segment_list->get(); if (next == nullptr) { @@ -125,7 +125,7 @@ G1SegmentedArraySegment* G1SegmentedArray::create_new_segment( next = new G1SegmentedArraySegment(slot_size(), num_slots, prev); } else { assert(slot_size() == next->slot_size() , - "Mismatch %d != %d Slot %zu", slot_size(), next->slot_size(), sizeof(Slot)); + "Mismatch %d != %d", slot_size(), next->slot_size()); next->reset(prev); } @@ -148,14 +148,14 @@ G1SegmentedArraySegment* G1SegmentedArray::create_new_segment( } } -template -uint G1SegmentedArray::slot_size() const { +template +uint G1SegmentedArray::slot_size() const { return _alloc_options->slot_size(); } -template -G1SegmentedArray::G1SegmentedArray(const G1SegmentedArrayAllocOptions* alloc_options, - G1SegmentedArrayFreeList* free_segment_list) : +template +G1SegmentedArray::G1SegmentedArray(const G1SegmentedArrayAllocOptions* alloc_options, + G1SegmentedArrayFreeList* free_segment_list) : _alloc_options(alloc_options), _first(nullptr), _last(nullptr), @@ -167,13 +167,13 @@ G1SegmentedArray::G1SegmentedArray(const G1SegmentedArrayAllocOption assert(_free_segment_list != nullptr, "precondition!"); } -template -G1SegmentedArray::~G1SegmentedArray() { +template +G1SegmentedArray::~G1SegmentedArray() { drop_all(); } -template -void G1SegmentedArray::drop_all() { +template +void G1SegmentedArray::drop_all() { G1SegmentedArraySegment* cur = Atomic::load_acquire(&_first); if (cur != nullptr) { @@ -209,8 +209,8 @@ void G1SegmentedArray::drop_all() { _num_allocated_slots = 0; } -template -Slot* G1SegmentedArray::allocate() { +template +void* G1SegmentedArray::allocate() { assert(slot_size() > 0, "instance size not set."); G1SegmentedArraySegment* cur = Atomic::load_acquire(&_first); @@ -219,7 +219,7 @@ Slot* G1SegmentedArray::allocate() { } while (true) { - Slot* slot = (Slot*)cur->get_new_slot(); + void* slot = cur->get_new_slot(); if (slot != nullptr) { Atomic::inc(&_num_allocated_slots, memory_order_relaxed); guarantee(is_aligned(slot, _alloc_options->slot_alignment()), @@ -232,8 +232,8 @@ Slot* G1SegmentedArray::allocate() { } } -template -inline uint G1SegmentedArray::num_segments() const { +template +inline uint G1SegmentedArray::num_segments() const { return Atomic::load(&_num_segments); } @@ -251,17 +251,17 @@ public: } }; -template -uint G1SegmentedArray::calculate_length() const { +template +uint G1SegmentedArray::calculate_length() const { LengthClosure closure; iterate_segments(closure); return closure.length(); } #endif -template +template template -void G1SegmentedArray::iterate_segments(SegmentClosure& closure) const { +void G1SegmentedArray::iterate_segments(SegmentClosure& closure) const { G1SegmentedArraySegment* cur = Atomic::load_acquire(&_first); assert((cur != nullptr) == (_last != nullptr), diff --git a/src/hotspot/share/gc/g1/heapRegion.inline.hpp b/src/hotspot/share/gc/g1/heapRegion.inline.hpp index 3d61cc1620af3cfb6855ebc4a8b260b41ea68668..e94320fbdb496d7dc6ac53da0bb05e823e08c8c8 100644 --- a/src/hotspot/share/gc/g1/heapRegion.inline.hpp +++ b/src/hotspot/share/gc/g1/heapRegion.inline.hpp @@ -329,16 +329,6 @@ HeapWord* HeapRegion::oops_on_memregion_seq_iterate_careful(MemRegion mr, // Find the obj that extends onto mr.start(). HeapWord* cur = block_start(start); -#ifdef ASSERT - { - assert(cur <= start, - "cur: " PTR_FORMAT ", start: " PTR_FORMAT, p2i(cur), p2i(start)); - HeapWord* next = cur + block_size(cur); - assert(start < next, - "start: " PTR_FORMAT ", next: " PTR_FORMAT, p2i(start), p2i(next)); - } -#endif - const G1CMBitMap* const bitmap = g1h->concurrent_mark()->prev_mark_bitmap(); while (true) { oop obj = cast_to_oop(cur); diff --git a/src/hotspot/share/gc/g1/heapRegionRemSet.inline.hpp b/src/hotspot/share/gc/g1/heapRegionRemSet.inline.hpp index 4bb8e6c4ff90212a5bcedd8a3e9b64d8c8c94b1d..a0e920175e1509688e00a37e5a0c4149dde7b40d 100644 --- a/src/hotspot/share/gc/g1/heapRegionRemSet.inline.hpp +++ b/src/hotspot/share/gc/g1/heapRegionRemSet.inline.hpp @@ -78,7 +78,7 @@ public: }; template class CardOrRanges> -class G1HeapRegionRemSetMergeCardClosure : public G1CardSet::CardSetPtrClosure { +class G1HeapRegionRemSetMergeCardClosure : public G1CardSet::ContainerPtrClosure { G1CardSet* _card_set; Closure& _cl; uint _log_card_regions_per_region; @@ -98,11 +98,11 @@ public: _log_card_region_size(log_card_region_size) { } - void do_cardsetptr(uint card_region_idx, size_t num_occupied, G1CardSet::CardSetPtr card_set) override { + void do_containerptr(uint card_region_idx, size_t num_occupied, G1CardSet::ContainerPtr container) override { CardOrRanges cl(_cl, card_region_idx >> _log_card_regions_per_region, (card_region_idx & _card_regions_per_region_mask) << _log_card_region_size); - _card_set->iterate_cards_or_ranges_in_container(card_set, cl); + _card_set->iterate_cards_or_ranges_in_container(container, cl); } }; diff --git a/src/hotspot/share/gc/parallel/parallelScavengeHeap.cpp b/src/hotspot/share/gc/parallel/parallelScavengeHeap.cpp index 3a4774d15ca5f523265c3bbbe1d23d27618ffc07..e47730d47e1fe714ef634a0ad9bf90d50e502b08 100644 --- a/src/hotspot/share/gc/parallel/parallelScavengeHeap.cpp +++ b/src/hotspot/share/gc/parallel/parallelScavengeHeap.cpp @@ -798,6 +798,16 @@ void ParallelScavengeHeap::resize_old_gen(size_t desired_free_space) { _old_gen->resize(desired_free_space); } +HeapWord* ParallelScavengeHeap::allocate_loaded_archive_space(size_t size) { + return _old_gen->allocate(size); +} + +void ParallelScavengeHeap::complete_loaded_archive_space(MemRegion archive_space) { + assert(_old_gen->object_space()->used_region().contains(archive_space), + "Archive space not contained in old gen"); + _old_gen->complete_loaded_archive_space(archive_space); +} + #ifndef PRODUCT void ParallelScavengeHeap::record_gen_tops_before_GC() { if (ZapUnusedHeapArea) { diff --git a/src/hotspot/share/gc/parallel/parallelScavengeHeap.hpp b/src/hotspot/share/gc/parallel/parallelScavengeHeap.hpp index 0a81c0b1315f9995a8090e50a78cd8d5766578f4..3ee16e5d8b9840851d01916a5dc526c98d001d39 100644 --- a/src/hotspot/share/gc/parallel/parallelScavengeHeap.hpp +++ b/src/hotspot/share/gc/parallel/parallelScavengeHeap.hpp @@ -184,8 +184,7 @@ class ParallelScavengeHeap : public CollectedHeap { bool is_in_reserved(const void* p) const; - bool is_in_young(oop p); // reserved part - bool is_in_old(oop p); // reserved part + bool is_in_young(const oop p) const; MemRegion reserved_region() const { return _reserved; } HeapWord* base() const { return _reserved.start(); } @@ -273,6 +272,11 @@ class ParallelScavengeHeap : public CollectedHeap { WorkerThreads& workers() { return _workers; } + + // Support for loading objects from CDS archive into the heap + bool can_load_archived_objects() const { return UseCompressedOops; } + HeapWord* allocate_loaded_archive_space(size_t size); + void complete_loaded_archive_space(MemRegion archive_space); }; // Class that can be used to print information about the diff --git a/src/hotspot/share/gc/parallel/parallelScavengeHeap.inline.hpp b/src/hotspot/share/gc/parallel/parallelScavengeHeap.inline.hpp index a867c689c984023bab102da76319aef4706003d4..80efa1b8fc6f6e5d6e74b7ecede99973cf03f5d7 100644 --- a/src/hotspot/share/gc/parallel/parallelScavengeHeap.inline.hpp +++ b/src/hotspot/share/gc/parallel/parallelScavengeHeap.inline.hpp @@ -43,7 +43,7 @@ inline void ParallelScavengeHeap::invoke_scavenge() { PSScavenge::invoke(); } -inline bool ParallelScavengeHeap::is_in_young(oop p) { +inline bool ParallelScavengeHeap::is_in_young(const oop p) const { // Assumes the the old gen address range is lower than that of the young gen. bool result = cast_from_oop(p) >= young_gen()->reserved().start(); assert(result == young_gen()->is_in_reserved(p), diff --git a/src/hotspot/share/gc/parallel/psCardTable.cpp b/src/hotspot/share/gc/parallel/psCardTable.cpp index 55709a19436e1e2fd3f646f42e9ce06790e313ad..bdad1707ca13925e228eea1d752fbb06219f7fe8 100644 --- a/src/hotspot/share/gc/parallel/psCardTable.cpp +++ b/src/hotspot/share/gc/parallel/psCardTable.cpp @@ -303,7 +303,8 @@ void PSCardTable::scavenge_contents_parallel(ObjectStartArray* start_array, } assert(*dirty_l != clean_card, "inv"); - assert(*dirty_r == clean_card || dirty_r == iter_limit_r, "inv"); + assert(*dirty_r == clean_card || dirty_r >= clear_limit_r, + "clean card or belonging to next stripe"); // Process this non-empty dirty chunk in two steps: { diff --git a/src/hotspot/share/gc/parallel/psClosure.inline.hpp b/src/hotspot/share/gc/parallel/psClosure.inline.hpp index cd78583bb80c74e0347423976bd73013d7f18d21..3499b179f46688da825d16af50b85eb73c613042 100644 --- a/src/hotspot/share/gc/parallel/psClosure.inline.hpp +++ b/src/hotspot/share/gc/parallel/psClosure.inline.hpp @@ -60,9 +60,12 @@ private: PSPromotionManager* _promotion_manager; template void do_oop_work(T *p) { - if (PSScavenge::should_scavenge(p)) { - // We never card mark roots, maybe call a func without test? - _promotion_manager->copy_and_push_safe_barrier(p); + assert(!ParallelScavengeHeap::heap()->is_in_reserved(p), "roots should be outside of heap"); + oop o = RawAccess<>::oop_load(p); + if (PSScavenge::is_obj_in_young(o)) { + assert(!PSScavenge::is_obj_in_to_space(o), "Revisiting roots?"); + oop new_obj = _promotion_manager->copy_to_survivor_space(o); + RawAccess::oop_store(p, new_obj); } } public: diff --git a/src/hotspot/share/gc/parallel/psCompactionManager.cpp b/src/hotspot/share/gc/parallel/psCompactionManager.cpp index c6bb7bf1e996b85e2efb11bf54cbe83e6f9d0ef5..dc68d999b271fd07cf77f3166e8b3b42b59ecfd8 100644 --- a/src/hotspot/share/gc/parallel/psCompactionManager.cpp +++ b/src/hotspot/share/gc/parallel/psCompactionManager.cpp @@ -113,7 +113,19 @@ ParCompactionManager::gc_thread_compaction_manager(uint index) { return _manager_array[index]; } -bool ParCompactionManager::transfer_from_overflow_stack(ObjArrayTask& task) { +inline void ParCompactionManager::publish_and_drain_oop_tasks() { + oop obj; + while (marking_stack()->pop_overflow(obj)) { + if (!marking_stack()->try_push_to_taskqueue(obj)) { + follow_contents(obj); + } + } + while (marking_stack()->pop_local(obj)) { + follow_contents(obj); + } +} + +bool ParCompactionManager::publish_or_pop_objarray_tasks(ObjArrayTask& task) { while (_objarray_stack.pop_overflow(task)) { if (!_objarray_stack.try_push_to_taskqueue(task)) { return true; @@ -126,19 +138,12 @@ void ParCompactionManager::follow_marking_stacks() { do { // First, try to move tasks from the overflow stack into the shared buffer, so // that other threads can steal. Otherwise process the overflow stack first. - oop obj; - while (marking_stack()->pop_overflow(obj)) { - if (!marking_stack()->try_push_to_taskqueue(obj)) { - follow_contents(obj); - } - } - while (marking_stack()->pop_local(obj)) { - follow_contents(obj); - } + publish_and_drain_oop_tasks(); // Process ObjArrays one at a time to avoid marking stack bloat. ObjArrayTask task; - if (transfer_from_overflow_stack(task) || _objarray_stack.pop_local(task)) { + if (publish_or_pop_objarray_tasks(task) || + _objarray_stack.pop_local(task)) { follow_array((objArrayOop)task.obj(), task.index()); } } while (!marking_stacks_empty()); diff --git a/src/hotspot/share/gc/parallel/psCompactionManager.hpp b/src/hotspot/share/gc/parallel/psCompactionManager.hpp index 0cb5d33e0f5476b6c3b517ff04d87418bc0a1d3b..18f8a459434079c353c1f40b8b4b1ce432d09738 100644 --- a/src/hotspot/share/gc/parallel/psCompactionManager.hpp +++ b/src/hotspot/share/gc/parallel/psCompactionManager.hpp @@ -97,7 +97,12 @@ class ParCompactionManager : public CHeapObj { static void initialize(ParMarkBitMap* mbm); - bool transfer_from_overflow_stack(ObjArrayTask& task); + void publish_and_drain_oop_tasks(); + // Try to publish all contents from the objArray task queue overflow stack to + // the shared objArray stack. + // Returns true and a valid task if there has not been enough space in the shared + // objArray stack, otherwise returns false and the task is invalid. + bool publish_or_pop_objarray_tasks(ObjArrayTask& task); protected: // Array of task queues. Needed by the task terminator. static RegionTaskQueueSet* region_task_queues() { return _region_task_queues; } diff --git a/src/hotspot/share/gc/parallel/psOldGen.cpp b/src/hotspot/share/gc/parallel/psOldGen.cpp index 3c01fb9eb1712f6759c83651c6569e07149c0223..7599025657bf4446e765e041baa7e8497c5a9463 100644 --- a/src/hotspot/share/gc/parallel/psOldGen.cpp +++ b/src/hotspot/share/gc/parallel/psOldGen.cpp @@ -283,6 +283,15 @@ void PSOldGen::shrink(size_t bytes) { } } +void PSOldGen::complete_loaded_archive_space(MemRegion archive_space) { + HeapWord* cur = archive_space.start(); + while (cur < archive_space.end()) { + _start_array.allocate_block(cur); + size_t word_size = cast_to_oop(cur)->size(); + cur += word_size; + } +} + void PSOldGen::resize(size_t desired_free_space) { const size_t alignment = virtual_space()->alignment(); const size_t size_before = virtual_space()->committed_size(); diff --git a/src/hotspot/share/gc/parallel/psOldGen.hpp b/src/hotspot/share/gc/parallel/psOldGen.hpp index 713098056c6d9939d3a5ecfc9f5b903ee78c52cb..d5f6f90a80cce904b60982f64ccf1f1e2e3d5d94 100644 --- a/src/hotspot/share/gc/parallel/psOldGen.hpp +++ b/src/hotspot/share/gc/parallel/psOldGen.hpp @@ -133,6 +133,8 @@ class PSOldGen : public CHeapObj { return virtual_space()->uncommitted_size() == 0; } + void complete_loaded_archive_space(MemRegion archive_space); + // Calculating new sizes void resize(size_t desired_free_space); diff --git a/src/hotspot/share/gc/parallel/psParallelCompact.cpp b/src/hotspot/share/gc/parallel/psParallelCompact.cpp index cb8dd999f5dabbbbaef66c7a4237ba53eb1b6d8a..22b5bc41f343fd2d3bce7e560323cb401c7b9286 100644 --- a/src/hotspot/share/gc/parallel/psParallelCompact.cpp +++ b/src/hotspot/share/gc/parallel/psParallelCompact.cpp @@ -845,40 +845,15 @@ PSParallelCompact::IsAliveClosure PSParallelCompact::_is_alive_closure; bool PSParallelCompact::IsAliveClosure::do_object_b(oop p) { return mark_bitmap()->is_marked(p); } -class PCReferenceProcessor: public ReferenceProcessor { -public: - PCReferenceProcessor( - BoolObjectClosure* is_subject_to_discovery, - BoolObjectClosure* is_alive_non_header) : - ReferenceProcessor(is_subject_to_discovery, - ParallelGCThreads, // mt processing degree - ParallelGCThreads, // mt discovery degree - true, // atomic_discovery - is_alive_non_header) { - } - - template bool discover(oop obj, ReferenceType type) { - T* referent_addr = (T*) java_lang_ref_Reference::referent_addr_raw(obj); - T heap_oop = RawAccess<>::oop_load(referent_addr); - oop referent = CompressedOops::decode_not_null(heap_oop); - return PSParallelCompact::mark_bitmap()->is_unmarked(referent) - && ReferenceProcessor::discover_reference(obj, type); - } - virtual bool discover_reference(oop obj, ReferenceType type) { - if (UseCompressedOops) { - return discover(obj, type); - } else { - return discover(obj, type); - } - } -}; - void PSParallelCompact::post_initialize() { ParallelScavengeHeap* heap = ParallelScavengeHeap::heap(); _span_based_discoverer.set_span(heap->reserved_region()); _ref_processor = - new PCReferenceProcessor(&_span_based_discoverer, - &_is_alive_closure); // non-header is alive closure + new ReferenceProcessor(&_span_based_discoverer, + ParallelGCThreads, // mt processing degree + ParallelGCThreads, // mt discovery degree + false, // concurrent_discovery + &_is_alive_closure); // non-header is alive closure _counters = new CollectorCounters("Parallel full collection pauses", 1); diff --git a/src/hotspot/share/gc/parallel/psPromotionLAB.cpp b/src/hotspot/share/gc/parallel/psPromotionLAB.cpp index 312db67606a5e096d57692d252d49888a8245aa6..bab79b25a13ebc1d19c44475a50d182406b7fabe 100644 --- a/src/hotspot/share/gc/parallel/psPromotionLAB.cpp +++ b/src/hotspot/share/gc/parallel/psPromotionLAB.cpp @@ -85,18 +85,19 @@ void PSPromotionLAB::flush() { _state = flushed; } -bool PSPromotionLAB::unallocate_object(HeapWord* obj, size_t obj_size) { +void PSPromotionLAB::unallocate_object(HeapWord* obj, size_t obj_size) { assert(ParallelScavengeHeap::heap()->is_in(obj), "Object outside heap"); + // If the object is inside this LAB, we just bump-down the `top` pointer. + // Otherwise, we overwrite it with a filler object. if (contains(obj)) { HeapWord* object_end = obj + obj_size; assert(object_end == top(), "Not matching last allocation"); set_top(obj); - return true; + } else { + CollectedHeap::fill_with_object(obj, obj_size); } - - return false; } // Fill all remaining lab space with an unreachable object. diff --git a/src/hotspot/share/gc/parallel/psPromotionLAB.hpp b/src/hotspot/share/gc/parallel/psPromotionLAB.hpp index 239a1140a8a844937df33f1876bf469db8f44860..7e8f8857dcd4b13161b1c8de31ded479db1293a5 100644 --- a/src/hotspot/share/gc/parallel/psPromotionLAB.hpp +++ b/src/hotspot/share/gc/parallel/psPromotionLAB.hpp @@ -72,7 +72,7 @@ class PSPromotionLAB : public CHeapObj { bool is_flushed() { return _state == flushed; } - bool unallocate_object(HeapWord* obj, size_t obj_size); + void unallocate_object(HeapWord* obj, size_t obj_size); // Returns a subregion containing all objects in this space. MemRegion used_region() { return MemRegion(bottom(), top()); } diff --git a/src/hotspot/share/gc/parallel/psPromotionManager.cpp b/src/hotspot/share/gc/parallel/psPromotionManager.cpp index 9c6b8acf62426bc27416252f2518bdbdd6fce9a4..652342ae31f5e1240f91d9bdcaed2c5ef468480d 100644 --- a/src/hotspot/share/gc/parallel/psPromotionManager.cpp +++ b/src/hotspot/share/gc/parallel/psPromotionManager.cpp @@ -180,8 +180,7 @@ PSPromotionManager::PSPromotionManager() { uint queue_size; queue_size = claimed_stack_depth()->max_elems(); - _totally_drain = (ParallelGCThreads == 1) || (GCDrainStackTargetSize == 0); - if (_totally_drain) { + if (ParallelGCThreads == 1) { _target_stack_size = 0; } else { // don't let the target stack size to be more than 1/4 of the entries @@ -227,7 +226,7 @@ void PSPromotionManager::restore_preserved_marks() { } void PSPromotionManager::drain_stacks_depth(bool totally_drain) { - totally_drain = totally_drain || _totally_drain; + totally_drain = totally_drain || (_target_stack_size == 0); PSScannerTasksQueue* const tq = claimed_stack_depth(); do { diff --git a/src/hotspot/share/gc/parallel/psPromotionManager.hpp b/src/hotspot/share/gc/parallel/psPromotionManager.hpp index bd48135f1346718806ee806076e4ca9d91ba0aa0..a1d2b38db31fa17a32aa255187f21ed063f72fa4 100644 --- a/src/hotspot/share/gc/parallel/psPromotionManager.hpp +++ b/src/hotspot/share/gc/parallel/psPromotionManager.hpp @@ -83,7 +83,6 @@ class PSPromotionManager { PSScannerTasksQueue _claimed_stack_depth; - bool _totally_drain; uint _target_stack_size; uint _array_chunk_size; diff --git a/src/hotspot/share/gc/parallel/psPromotionManager.inline.hpp b/src/hotspot/share/gc/parallel/psPromotionManager.inline.hpp index b3f1c7297f40a2261ab9cba8ad8a27fcb00337e1..64ee5f286b5317c23a361d71b2896fc30529436e 100644 --- a/src/hotspot/share/gc/parallel/psPromotionManager.inline.hpp +++ b/src/hotspot/share/gc/parallel/psPromotionManager.inline.hpp @@ -290,39 +290,28 @@ inline oop PSPromotionManager::copy_unmarked_to_survivor_space(oop o, assert(o->is_forwarded(), "Object must be forwarded if the cas failed."); assert(o->forwardee() == forwardee, "invariant"); - // Try to deallocate the space. If it was directly allocated we cannot - // deallocate it, so we have to test. If the deallocation fails, - // overwrite with a filler object. if (new_obj_is_tenured) { - if (!_old_lab.unallocate_object(cast_from_oop(new_obj), new_obj_size)) { - CollectedHeap::fill_with_object(cast_from_oop(new_obj), new_obj_size); - } - } else if (!_young_lab.unallocate_object(cast_from_oop(new_obj), new_obj_size)) { - CollectedHeap::fill_with_object(cast_from_oop(new_obj), new_obj_size); + _old_lab.unallocate_object(cast_from_oop(new_obj), new_obj_size); + } else { + _young_lab.unallocate_object(cast_from_oop(new_obj), new_obj_size); } return forwardee; } } // Attempt to "claim" oop at p via CAS, push the new obj if successful -// This version tests the oop* to make sure it is within the heap before -// attempting marking. template inline void PSPromotionManager::copy_and_push_safe_barrier(T* p) { + assert(ParallelScavengeHeap::heap()->is_in_reserved(p), "precondition"); assert(should_scavenge(p, true), "revisiting object?"); oop o = RawAccess::oop_load(p); oop new_obj = copy_to_survivor_space(o); RawAccess::oop_store(p, new_obj); - // We cannot mark without test, as some code passes us pointers - // that are outside the heap. These pointers are either from roots - // or from metadata. - if ((!PSScavenge::is_obj_in_young((HeapWord*)p)) && - ParallelScavengeHeap::heap()->is_in_reserved(p)) { - if (PSScavenge::is_obj_in_young(new_obj)) { - PSScavenge::card_table()->inline_write_ref_field_gc(p, new_obj); - } + if (!PSScavenge::is_obj_in_young((HeapWord*)p) && + PSScavenge::is_obj_in_young(new_obj)) { + PSScavenge::card_table()->inline_write_ref_field_gc(p, new_obj); } } diff --git a/src/hotspot/share/gc/parallel/psScavenge.hpp b/src/hotspot/share/gc/parallel/psScavenge.hpp index c575e8a3f2ca4d8ad6250bbaa4539dacc27751d3..01bc154e55291dae3bd9690d99af4978a4d846b9 100644 --- a/src/hotspot/share/gc/parallel/psScavenge.hpp +++ b/src/hotspot/share/gc/parallel/psScavenge.hpp @@ -135,6 +135,10 @@ class PSScavenge: AllStatic { inline static bool is_obj_in_young(HeapWord* o) { return o >= _young_generation_boundary; } + + static bool is_obj_in_to_space(oop o) { + return ParallelScavengeHeap::young_gen()->to_space()->contains(o); + } }; #endif // SHARE_GC_PARALLEL_PSSCAVENGE_HPP diff --git a/src/hotspot/share/gc/serial/tenuredGeneration.cpp b/src/hotspot/share/gc/serial/tenuredGeneration.cpp index acf19426a957289003c8aaf4f7d4998a698c434d..08aede2880f2acdda741f3b0cb1ba6c169c299f3 100644 --- a/src/hotspot/share/gc/serial/tenuredGeneration.cpp +++ b/src/hotspot/share/gc/serial/tenuredGeneration.cpp @@ -26,8 +26,8 @@ #include "gc/serial/genMarkSweep.hpp" #include "gc/serial/tenuredGeneration.inline.hpp" #include "gc/shared/blockOffsetTable.inline.hpp" -#include "gc/shared/cardGeneration.inline.hpp" #include "gc/shared/collectorCounters.hpp" +#include "gc/shared/gcLocker.hpp" #include "gc/shared/gcTimer.hpp" #include "gc/shared/gcTrace.hpp" #include "gc/shared/genCollectedHeap.hpp" @@ -40,13 +40,286 @@ #include "runtime/java.hpp" #include "utilities/macros.hpp" +bool TenuredGeneration::grow_by(size_t bytes) { + assert_correct_size_change_locking(); + bool result = _virtual_space.expand_by(bytes); + if (result) { + size_t new_word_size = + heap_word_size(_virtual_space.committed_size()); + MemRegion mr(space()->bottom(), new_word_size); + // Expand card table + GenCollectedHeap::heap()->rem_set()->resize_covered_region(mr); + // Expand shared block offset array + _bts->resize(new_word_size); + + // Fix for bug #4668531 + if (ZapUnusedHeapArea) { + MemRegion mangle_region(space()->end(), + (HeapWord*)_virtual_space.high()); + SpaceMangler::mangle_region(mangle_region); + } + + // Expand space -- also expands space's BOT + // (which uses (part of) shared array above) + space()->set_end((HeapWord*)_virtual_space.high()); + + // update the space and generation capacity counters + update_counters(); + + size_t new_mem_size = _virtual_space.committed_size(); + size_t old_mem_size = new_mem_size - bytes; + log_trace(gc, heap)("Expanding %s from " SIZE_FORMAT "K by " SIZE_FORMAT "K to " SIZE_FORMAT "K", + name(), old_mem_size/K, bytes/K, new_mem_size/K); + } + return result; +} + +bool TenuredGeneration::expand(size_t bytes, size_t expand_bytes) { + assert_locked_or_safepoint(Heap_lock); + if (bytes == 0) { + return true; // That's what grow_by(0) would return + } + size_t aligned_bytes = ReservedSpace::page_align_size_up(bytes); + if (aligned_bytes == 0){ + // The alignment caused the number of bytes to wrap. An expand_by(0) will + // return true with the implication that an expansion was done when it + // was not. A call to expand implies a best effort to expand by "bytes" + // but not a guarantee. Align down to give a best effort. This is likely + // the most that the generation can expand since it has some capacity to + // start with. + aligned_bytes = ReservedSpace::page_align_size_down(bytes); + } + size_t aligned_expand_bytes = ReservedSpace::page_align_size_up(expand_bytes); + bool success = false; + if (aligned_expand_bytes > aligned_bytes) { + success = grow_by(aligned_expand_bytes); + } + if (!success) { + success = grow_by(aligned_bytes); + } + if (!success) { + success = grow_to_reserved(); + } + if (success && GCLocker::is_active_and_needs_gc()) { + log_trace(gc, heap)("Garbage collection disabled, expanded heap instead"); + } + + return success; +} + +bool TenuredGeneration::grow_to_reserved() { + assert_correct_size_change_locking(); + bool success = true; + const size_t remaining_bytes = _virtual_space.uncommitted_size(); + if (remaining_bytes > 0) { + success = grow_by(remaining_bytes); + DEBUG_ONLY(if (!success) log_warning(gc)("grow to reserved failed");) + } + return success; +} + +void TenuredGeneration::shrink(size_t bytes) { + assert_correct_size_change_locking(); + + size_t size = ReservedSpace::page_align_size_down(bytes); + if (size == 0) { + return; + } + + // Shrink committed space + _virtual_space.shrink_by(size); + // Shrink space; this also shrinks the space's BOT + space()->set_end((HeapWord*) _virtual_space.high()); + size_t new_word_size = heap_word_size(space()->capacity()); + // Shrink the shared block offset array + _bts->resize(new_word_size); + MemRegion mr(space()->bottom(), new_word_size); + // Shrink the card table + GenCollectedHeap::heap()->rem_set()->resize_covered_region(mr); + + size_t new_mem_size = _virtual_space.committed_size(); + size_t old_mem_size = new_mem_size + size; + log_trace(gc, heap)("Shrinking %s from " SIZE_FORMAT "K to " SIZE_FORMAT "K", + name(), old_mem_size/K, new_mem_size/K); +} + +// Objects in this generation may have moved, invalidate this +// generation's cards. +void TenuredGeneration::invalidate_remembered_set() { + _rs->invalidate(used_region()); +} + +void TenuredGeneration::compute_new_size_inner() { + assert(_shrink_factor <= 100, "invalid shrink factor"); + size_t current_shrink_factor = _shrink_factor; + if (ShrinkHeapInSteps) { + // Always reset '_shrink_factor' if the heap is shrunk in steps. + // If we shrink the heap in this iteration, '_shrink_factor' will + // be recomputed based on the old value further down in this fuction. + _shrink_factor = 0; + } + + // We don't have floating point command-line arguments + // Note: argument processing ensures that MinHeapFreeRatio < 100. + const double minimum_free_percentage = MinHeapFreeRatio / 100.0; + const double maximum_used_percentage = 1.0 - minimum_free_percentage; + + // Compute some numbers about the state of the heap. + const size_t used_after_gc = used(); + const size_t capacity_after_gc = capacity(); + + const double min_tmp = used_after_gc / maximum_used_percentage; + size_t minimum_desired_capacity = (size_t)MIN2(min_tmp, double(max_uintx)); + // Don't shrink less than the initial generation size + minimum_desired_capacity = MAX2(minimum_desired_capacity, initial_size()); + assert(used_after_gc <= minimum_desired_capacity, "sanity check"); + + const size_t free_after_gc = free(); + const double free_percentage = ((double)free_after_gc) / capacity_after_gc; + log_trace(gc, heap)("TenuredGeneration::compute_new_size:"); + log_trace(gc, heap)(" minimum_free_percentage: %6.2f maximum_used_percentage: %6.2f", + minimum_free_percentage, + maximum_used_percentage); + log_trace(gc, heap)(" free_after_gc : %6.1fK used_after_gc : %6.1fK capacity_after_gc : %6.1fK", + free_after_gc / (double) K, + used_after_gc / (double) K, + capacity_after_gc / (double) K); + log_trace(gc, heap)(" free_percentage: %6.2f", free_percentage); + + if (capacity_after_gc < minimum_desired_capacity) { + // If we have less free space than we want then expand + size_t expand_bytes = minimum_desired_capacity - capacity_after_gc; + // Don't expand unless it's significant + if (expand_bytes >= _min_heap_delta_bytes) { + expand(expand_bytes, 0); // safe if expansion fails + } + log_trace(gc, heap)(" expanding: minimum_desired_capacity: %6.1fK expand_bytes: %6.1fK _min_heap_delta_bytes: %6.1fK", + minimum_desired_capacity / (double) K, + expand_bytes / (double) K, + _min_heap_delta_bytes / (double) K); + return; + } + + // No expansion, now see if we want to shrink + size_t shrink_bytes = 0; + // We would never want to shrink more than this + size_t max_shrink_bytes = capacity_after_gc - minimum_desired_capacity; + + if (MaxHeapFreeRatio < 100) { + const double maximum_free_percentage = MaxHeapFreeRatio / 100.0; + const double minimum_used_percentage = 1.0 - maximum_free_percentage; + const double max_tmp = used_after_gc / minimum_used_percentage; + size_t maximum_desired_capacity = (size_t)MIN2(max_tmp, double(max_uintx)); + maximum_desired_capacity = MAX2(maximum_desired_capacity, initial_size()); + log_trace(gc, heap)(" maximum_free_percentage: %6.2f minimum_used_percentage: %6.2f", + maximum_free_percentage, minimum_used_percentage); + log_trace(gc, heap)(" _capacity_at_prologue: %6.1fK minimum_desired_capacity: %6.1fK maximum_desired_capacity: %6.1fK", + _capacity_at_prologue / (double) K, + minimum_desired_capacity / (double) K, + maximum_desired_capacity / (double) K); + assert(minimum_desired_capacity <= maximum_desired_capacity, + "sanity check"); + + if (capacity_after_gc > maximum_desired_capacity) { + // Capacity too large, compute shrinking size + shrink_bytes = capacity_after_gc - maximum_desired_capacity; + if (ShrinkHeapInSteps) { + // If ShrinkHeapInSteps is true (the default), + // we don't want to shrink all the way back to initSize if people call + // System.gc(), because some programs do that between "phases" and then + // we'd just have to grow the heap up again for the next phase. So we + // damp the shrinking: 0% on the first call, 10% on the second call, 40% + // on the third call, and 100% by the fourth call. But if we recompute + // size without shrinking, it goes back to 0%. + shrink_bytes = shrink_bytes / 100 * current_shrink_factor; + if (current_shrink_factor == 0) { + _shrink_factor = 10; + } else { + _shrink_factor = MIN2(current_shrink_factor * 4, (size_t) 100); + } + } + assert(shrink_bytes <= max_shrink_bytes, "invalid shrink size"); + log_trace(gc, heap)(" shrinking: initSize: %.1fK maximum_desired_capacity: %.1fK", + initial_size() / (double) K, maximum_desired_capacity / (double) K); + log_trace(gc, heap)(" shrink_bytes: %.1fK current_shrink_factor: " SIZE_FORMAT " new shrink factor: " SIZE_FORMAT " _min_heap_delta_bytes: %.1fK", + shrink_bytes / (double) K, + current_shrink_factor, + _shrink_factor, + _min_heap_delta_bytes / (double) K); + } + } + + if (capacity_after_gc > _capacity_at_prologue) { + // We might have expanded for promotions, in which case we might want to + // take back that expansion if there's room after GC. That keeps us from + // stretching the heap with promotions when there's plenty of room. + size_t expansion_for_promotion = capacity_after_gc - _capacity_at_prologue; + expansion_for_promotion = MIN2(expansion_for_promotion, max_shrink_bytes); + // We have two shrinking computations, take the largest + shrink_bytes = MAX2(shrink_bytes, expansion_for_promotion); + assert(shrink_bytes <= max_shrink_bytes, "invalid shrink size"); + log_trace(gc, heap)(" aggressive shrinking: _capacity_at_prologue: %.1fK capacity_after_gc: %.1fK expansion_for_promotion: %.1fK shrink_bytes: %.1fK", + capacity_after_gc / (double) K, + _capacity_at_prologue / (double) K, + expansion_for_promotion / (double) K, + shrink_bytes / (double) K); + } + // Don't shrink unless it's significant + if (shrink_bytes >= _min_heap_delta_bytes) { + shrink(shrink_bytes); + } +} + +void TenuredGeneration::space_iterate(SpaceClosure* blk, + bool usedOnly) { + blk->do_space(space()); +} + +void TenuredGeneration::younger_refs_iterate(OopIterateClosure* blk) { + // Apply "cl->do_oop" to (the address of) (exactly) all the ref fields in + // "sp" that point into the young generation. + // The iteration is only over objects allocated at the start of the + // iterations; objects allocated as a result of applying the closure are + // not included. + + HeapWord* gen_boundary = reserved().start(); + _rs->younger_refs_in_space_iterate(space(), gen_boundary, blk); +} + TenuredGeneration::TenuredGeneration(ReservedSpace rs, size_t initial_byte_size, size_t min_byte_size, size_t max_byte_size, CardTableRS* remset) : - CardGeneration(rs, initial_byte_size, remset) + Generation(rs, initial_byte_size), _rs(remset), + _min_heap_delta_bytes(), _capacity_at_prologue(), + _used_at_prologue() { + // If we don't shrink the heap in steps, '_shrink_factor' is always 100%. + _shrink_factor = ShrinkHeapInSteps ? 0 : 100; + HeapWord* start = (HeapWord*)rs.base(); + size_t reserved_byte_size = rs.size(); + assert((uintptr_t(start) & 3) == 0, "bad alignment"); + assert((reserved_byte_size & 3) == 0, "bad alignment"); + MemRegion reserved_mr(start, heap_word_size(reserved_byte_size)); + _bts = new BlockOffsetSharedArray(reserved_mr, + heap_word_size(initial_byte_size)); + MemRegion committed_mr(start, heap_word_size(initial_byte_size)); + _rs->resize_covered_region(committed_mr); + + // Verify that the start and end of this generation is the start of a card. + // If this wasn't true, a single card could span more than on generation, + // which would cause problems when we commit/uncommit memory, and when we + // clear and dirty cards. + guarantee(_rs->is_aligned(reserved_mr.start()), "generation must be card aligned"); + if (reserved_mr.end() != GenCollectedHeap::heap()->reserved_region().end()) { + // Don't check at the very end of the heap as we'll assert that we're probing off + // the end if we try. + guarantee(_rs->is_aligned(reserved_mr.end()), "generation must be card aligned"); + } + _min_heap_delta_bytes = MinHeapDeltaBytes; + _capacity_at_prologue = initial_byte_size; + _used_at_prologue = 0; HeapWord* bottom = (HeapWord*) _virtual_space.low(); HeapWord* end = (HeapWord*) _virtual_space.high(); _the_space = new TenuredSpace(_bts, MemRegion(bottom, end)); @@ -114,7 +387,7 @@ void TenuredGeneration::compute_new_size() { const size_t used_after_gc = used(); const size_t capacity_after_gc = capacity(); - CardGeneration::compute_new_size(); + compute_new_size_inner(); assert(used() == used_after_gc && used_after_gc <= capacity(), "used: " SIZE_FORMAT " used_after_gc: " SIZE_FORMAT @@ -195,10 +468,6 @@ TenuredGeneration::expand_and_allocate(size_t word_size, bool is_tlab) { return _the_space->allocate(word_size); } -bool TenuredGeneration::expand(size_t bytes, size_t expand_bytes) { - return CardGeneration::expand(bytes, expand_bytes); -} - size_t TenuredGeneration::unsafe_max_alloc_nogc() const { return _the_space->free(); } diff --git a/src/hotspot/share/gc/serial/tenuredGeneration.hpp b/src/hotspot/share/gc/serial/tenuredGeneration.hpp index 410981de7582192c85e7b07724a12e171494d2ad..6f364a38f446f196779effe84533a2275f5493ca 100644 --- a/src/hotspot/share/gc/serial/tenuredGeneration.hpp +++ b/src/hotspot/share/gc/serial/tenuredGeneration.hpp @@ -26,36 +26,85 @@ #define SHARE_GC_SERIAL_TENUREDGENERATION_HPP #include "gc/serial/cSpaceCounters.hpp" -#include "gc/shared/cardGeneration.hpp" +#include "gc/shared/generation.hpp" #include "gc/shared/gcStats.hpp" #include "gc/shared/generationCounters.hpp" #include "utilities/macros.hpp" +class BlockOffsetSharedArray; +class CardTableRS; +class CompactibleSpace; + // TenuredGeneration models the heap containing old (promoted/tenured) objects -// contained in a single contiguous space. -// +// contained in a single contiguous space. This generation is covered by a card +// table, and uses a card-size block-offset array to implement block_start. // Garbage collection is performed using mark-compact. -class TenuredGeneration: public CardGeneration { +class TenuredGeneration: public Generation { friend class VMStructs; // Abstractly, this is a subtype that gets access to protected fields. friend class VM_PopulateDumpSharedSpace; protected: + + // This is shared with other generations. + CardTableRS* _rs; + // This is local to this generation. + BlockOffsetSharedArray* _bts; + + // Current shrinking effect: this damps shrinking when the heap gets empty. + size_t _shrink_factor; + + size_t _min_heap_delta_bytes; // Minimum amount to expand. + + // Some statistics from before gc started. + // These are gathered in the gc_prologue (and should_collect) + // to control growing/shrinking policy in spite of promotions. + size_t _capacity_at_prologue; + size_t _used_at_prologue; + + void assert_correct_size_change_locking(); + ContiguousSpace* _the_space; // Actual space holding objects GenerationCounters* _gen_counters; CSpaceCounters* _space_counters; - // Allocation failure - virtual bool expand(size_t bytes, size_t expand_bytes); - // Accessing spaces ContiguousSpace* space() const { return _the_space; } - void assert_correct_size_change_locking(); + // Attempt to expand the generation by "bytes". Expand by at a + // minimum "expand_bytes". Return true if some amount (not + // necessarily the full "bytes") was done. + bool expand(size_t bytes, size_t expand_bytes); + + // Shrink generation with specified size + void shrink(size_t bytes); + void compute_new_size_inner(); public: + virtual void compute_new_size(); + + virtual void invalidate_remembered_set(); + + // Grow generation with specified size (returns false if unable to grow) + bool grow_by(size_t bytes); + // Grow generation to reserved size. + bool grow_to_reserved(); + + size_t capacity() const; + size_t used() const; + size_t free() const; + MemRegion used_region() const; + + void space_iterate(SpaceClosure* blk, bool usedOnly = false); + + void younger_refs_iterate(OopIterateClosure* blk); + + bool is_in(const void* p) const; + + CompactibleSpace* first_compaction_space() const; + TenuredGeneration(ReservedSpace rs, size_t initial_byte_size, size_t min_byte_size, @@ -104,8 +153,6 @@ class TenuredGeneration: public CardGeneration { size_t word_size, bool is_tlab); - virtual void compute_new_size(); - // Performance Counter support void update_counters(); diff --git a/src/hotspot/share/gc/serial/tenuredGeneration.inline.hpp b/src/hotspot/share/gc/serial/tenuredGeneration.inline.hpp index f79d31786e2d1ad9f67338d4f6edf0246c145049..2e6a4ca56dfcc1d8d156ef24d527df32e553e95b 100644 --- a/src/hotspot/share/gc/serial/tenuredGeneration.inline.hpp +++ b/src/hotspot/share/gc/serial/tenuredGeneration.inline.hpp @@ -29,6 +29,30 @@ #include "gc/shared/space.inline.hpp" +inline size_t TenuredGeneration::capacity() const { + return space()->capacity(); +} + +inline size_t TenuredGeneration::used() const { + return space()->used(); +} + +inline size_t TenuredGeneration::free() const { + return space()->free(); +} + +inline MemRegion TenuredGeneration::used_region() const { + return space()->used_region(); +} + +inline bool TenuredGeneration::is_in(const void* p) const { + return space()->is_in(p); +} + +inline CompactibleSpace* TenuredGeneration::first_compaction_space() const { + return space(); +} + HeapWord* TenuredGeneration::allocate(size_t word_size, bool is_tlab) { assert(!is_tlab, "TenuredGeneration does not support TLAB allocation"); diff --git a/src/hotspot/share/gc/serial/vmStructs_serial.hpp b/src/hotspot/share/gc/serial/vmStructs_serial.hpp index 39905458d4c129f4e751d8a11f9f40ff78138e6c..0ba676706ab88e93ce9902742df251361bfaa2f1 100644 --- a/src/hotspot/share/gc/serial/vmStructs_serial.hpp +++ b/src/hotspot/share/gc/serial/vmStructs_serial.hpp @@ -45,7 +45,7 @@ declare_toplevel_type, \ declare_integer_type) \ declare_type(SerialHeap, GenCollectedHeap) \ - declare_type(TenuredGeneration, CardGeneration) \ + declare_type(TenuredGeneration, Generation) \ declare_type(TenuredSpace, OffsetTableContigSpace) \ \ declare_type(DefNewGeneration, Generation) \ diff --git a/src/hotspot/share/gc/shared/barrierSetNMethod.cpp b/src/hotspot/share/gc/shared/barrierSetNMethod.cpp index f98675d0b23d22bb685428697fae6dfa83fa4c05..efe2ff7b9e309e4a8c07a5de3b844466e2afe2ad 100644 --- a/src/hotspot/share/gc/shared/barrierSetNMethod.cpp +++ b/src/hotspot/share/gc/shared/barrierSetNMethod.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 @@ -28,6 +28,7 @@ #include "gc/shared/barrierSet.hpp" #include "gc/shared/barrierSetNMethod.hpp" #include "logging/log.hpp" +#include "runtime/frame.inline.hpp" #include "runtime/thread.hpp" #include "runtime/threadWXSetters.inline.hpp" #include "utilities/debug.hpp" @@ -54,6 +55,7 @@ int BarrierSetNMethod::nmethod_stub_entry_barrier(address* return_address_ptr) { MACOS_AARCH64_ONLY(ThreadWXEnable wx(WXWrite, Thread::current())); address return_address = *return_address_ptr; + AARCH64_PORT_ONLY(return_address = pauth_strip_pointer(return_address)); CodeBlob* cb = CodeCache::find_blob(return_address); assert(cb != NULL, "invariant"); diff --git a/src/hotspot/share/gc/shared/blockOffsetTable.cpp b/src/hotspot/share/gc/shared/blockOffsetTable.cpp index e350e70ad5fd5867a0b736f74f11842f44aaf222..2a4f3a48fa37158700ae00d13e66cf8e74bf3b4a 100644 --- a/src/hotspot/share/gc/shared/blockOffsetTable.cpp +++ b/src/hotspot/share/gc/shared/blockOffsetTable.cpp @@ -248,14 +248,10 @@ BlockOffsetArray::alloc_block(HeapWord* blk_start, HeapWord* blk_end) { single_block(blk_start, blk_end); } -// Action_mark - update the BOT for the block [blk_start, blk_end). -// Current typical use is for splitting a block. -// Action_single - udpate the BOT for an allocation. -// Action_verify - BOT verification. void BlockOffsetArray::do_block_internal(HeapWord* blk_start, HeapWord* blk_end, - Action action, bool reducing) { + bool reducing) { assert(_sp->is_in_reserved(blk_start), "reference must be into the space"); assert(_sp->is_in_reserved(blk_end-1), @@ -284,33 +280,13 @@ BlockOffsetArray::do_block_internal(HeapWord* blk_start, } assert(start_index <= end_index, "monotonicity of index_for()"); assert(boundary <= (HeapWord*)boundary_before_end, "tautology"); - switch (action) { - case Action_mark: { - if (init_to_zero()) { - _array->set_offset_array(start_index, boundary, blk_start, reducing); - break; - } // Else fall through to the next case - } - case Action_single: { - _array->set_offset_array(start_index, boundary, blk_start, reducing); - // We have finished marking the "offset card". We need to now - // mark the subsequent cards that this blk spans. - if (start_index < end_index) { - HeapWord* rem_st = _array->address_for_index(start_index) + BOTConstants::card_size_in_words(); - HeapWord* rem_end = _array->address_for_index(end_index) + BOTConstants::card_size_in_words(); - set_remainder_to_point_to_start(rem_st, rem_end, reducing); - } - break; - } - case Action_check: { - _array->check_offset_array(start_index, boundary, blk_start); - // We have finished checking the "offset card". We need to now - // check the subsequent cards that this blk spans. - check_all_cards(start_index + 1, end_index); - break; - } - default: - ShouldNotReachHere(); + _array->set_offset_array(start_index, boundary, blk_start, reducing); + // We have finished marking the "offset card". We need to now + // mark the subsequent cards that this blk spans. + if (start_index < end_index) { + HeapWord* rem_st = _array->address_for_index(start_index) + BOTConstants::card_size_in_words(); + HeapWord* rem_end = _array->address_for_index(end_index) + BOTConstants::card_size_in_words(); + set_remainder_to_point_to_start(rem_st, rem_end, reducing); } } } @@ -322,7 +298,7 @@ BlockOffsetArray::do_block_internal(HeapWord* blk_start, void BlockOffsetArray::single_block(HeapWord* blk_start, HeapWord* blk_end) { - do_block_internal(blk_start, blk_end, Action_single); + do_block_internal(blk_start, blk_end); } void BlockOffsetArray::verify() const { diff --git a/src/hotspot/share/gc/shared/blockOffsetTable.hpp b/src/hotspot/share/gc/shared/blockOffsetTable.hpp index 9a32594c123f666d233bf3033377faeaaab99054..6adc224876da21e137de1390020adcc93e17d2fb 100644 --- a/src/hotspot/share/gc/shared/blockOffsetTable.hpp +++ b/src/hotspot/share/gc/shared/blockOffsetTable.hpp @@ -279,14 +279,6 @@ class Space; class BlockOffsetArray: public BlockOffsetTable { friend class VMStructs; protected: - // The following enums are used by do_block_internal() below - enum Action { - Action_single, // BOT records a single block (see single_block()) - Action_mark, // BOT marks the start of a block (see mark_block()) - Action_check // Check that BOT records block correctly - // (see verify_single_block()). - }; - // The shared array, which is shared with other BlockOffsetArray's // corresponding to different spaces within a generation or span of // memory. @@ -315,7 +307,7 @@ class BlockOffsetArray: public BlockOffsetTable { void set_remainder_to_point_to_start_incl(size_t start, size_t end, bool reducing = false); // A helper function for BOT adjustment/verification work - void do_block_internal(HeapWord* blk_start, HeapWord* blk_end, Action action, bool reducing = false); + void do_block_internal(HeapWord* blk_start, HeapWord* blk_end, bool reducing = false); public: // The space may not have its bottom and top set yet, which is why the diff --git a/src/hotspot/share/gc/shared/cardGeneration.cpp b/src/hotspot/share/gc/shared/cardGeneration.cpp deleted file mode 100644 index 523f65c8cc3a5475b79d32b95f38da47017c1edf..0000000000000000000000000000000000000000 --- a/src/hotspot/share/gc/shared/cardGeneration.cpp +++ /dev/null @@ -1,318 +0,0 @@ -/* - * Copyright (c) 2014, 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. - * - */ - -#include "precompiled.hpp" - -#include "gc/shared/blockOffsetTable.inline.hpp" -#include "gc/shared/cardGeneration.inline.hpp" -#include "gc/shared/cardTableRS.hpp" -#include "gc/shared/gcLocker.hpp" -#include "gc/shared/genCollectedHeap.hpp" -#include "gc/shared/genOopClosures.inline.hpp" -#include "gc/shared/generationSpec.hpp" -#include "gc/shared/space.inline.hpp" -#include "memory/iterator.hpp" -#include "memory/memRegion.hpp" -#include "logging/log.hpp" -#include "runtime/java.hpp" - -CardGeneration::CardGeneration(ReservedSpace rs, - size_t initial_byte_size, - CardTableRS* remset) : - Generation(rs, initial_byte_size), _rs(remset), - _min_heap_delta_bytes(), _capacity_at_prologue(), - _used_at_prologue() -{ - // If we don't shrink the heap in steps, '_shrink_factor' is always 100%. - _shrink_factor = ShrinkHeapInSteps ? 0 : 100; - HeapWord* start = (HeapWord*)rs.base(); - size_t reserved_byte_size = rs.size(); - assert((uintptr_t(start) & 3) == 0, "bad alignment"); - assert((reserved_byte_size & 3) == 0, "bad alignment"); - MemRegion reserved_mr(start, heap_word_size(reserved_byte_size)); - _bts = new BlockOffsetSharedArray(reserved_mr, - heap_word_size(initial_byte_size)); - MemRegion committed_mr(start, heap_word_size(initial_byte_size)); - _rs->resize_covered_region(committed_mr); - - // Verify that the start and end of this generation is the start of a card. - // If this wasn't true, a single card could span more than on generation, - // which would cause problems when we commit/uncommit memory, and when we - // clear and dirty cards. - guarantee(_rs->is_aligned(reserved_mr.start()), "generation must be card aligned"); - if (reserved_mr.end() != GenCollectedHeap::heap()->reserved_region().end()) { - // Don't check at the very end of the heap as we'll assert that we're probing off - // the end if we try. - guarantee(_rs->is_aligned(reserved_mr.end()), "generation must be card aligned"); - } - _min_heap_delta_bytes = MinHeapDeltaBytes; - _capacity_at_prologue = initial_byte_size; - _used_at_prologue = 0; -} - -bool CardGeneration::grow_by(size_t bytes) { - assert_correct_size_change_locking(); - bool result = _virtual_space.expand_by(bytes); - if (result) { - size_t new_word_size = - heap_word_size(_virtual_space.committed_size()); - MemRegion mr(space()->bottom(), new_word_size); - // Expand card table - GenCollectedHeap::heap()->rem_set()->resize_covered_region(mr); - // Expand shared block offset array - _bts->resize(new_word_size); - - // Fix for bug #4668531 - if (ZapUnusedHeapArea) { - MemRegion mangle_region(space()->end(), - (HeapWord*)_virtual_space.high()); - SpaceMangler::mangle_region(mangle_region); - } - - // Expand space -- also expands space's BOT - // (which uses (part of) shared array above) - space()->set_end((HeapWord*)_virtual_space.high()); - - // update the space and generation capacity counters - update_counters(); - - size_t new_mem_size = _virtual_space.committed_size(); - size_t old_mem_size = new_mem_size - bytes; - log_trace(gc, heap)("Expanding %s from " SIZE_FORMAT "K by " SIZE_FORMAT "K to " SIZE_FORMAT "K", - name(), old_mem_size/K, bytes/K, new_mem_size/K); - } - return result; -} - -bool CardGeneration::expand(size_t bytes, size_t expand_bytes) { - assert_locked_or_safepoint(Heap_lock); - if (bytes == 0) { - return true; // That's what grow_by(0) would return - } - size_t aligned_bytes = ReservedSpace::page_align_size_up(bytes); - if (aligned_bytes == 0){ - // The alignment caused the number of bytes to wrap. An expand_by(0) will - // return true with the implication that an expansion was done when it - // was not. A call to expand implies a best effort to expand by "bytes" - // but not a guarantee. Align down to give a best effort. This is likely - // the most that the generation can expand since it has some capacity to - // start with. - aligned_bytes = ReservedSpace::page_align_size_down(bytes); - } - size_t aligned_expand_bytes = ReservedSpace::page_align_size_up(expand_bytes); - bool success = false; - if (aligned_expand_bytes > aligned_bytes) { - success = grow_by(aligned_expand_bytes); - } - if (!success) { - success = grow_by(aligned_bytes); - } - if (!success) { - success = grow_to_reserved(); - } - if (success && GCLocker::is_active_and_needs_gc()) { - log_trace(gc, heap)("Garbage collection disabled, expanded heap instead"); - } - - return success; -} - -bool CardGeneration::grow_to_reserved() { - assert_correct_size_change_locking(); - bool success = true; - const size_t remaining_bytes = _virtual_space.uncommitted_size(); - if (remaining_bytes > 0) { - success = grow_by(remaining_bytes); - DEBUG_ONLY(if (!success) log_warning(gc)("grow to reserved failed");) - } - return success; -} - -void CardGeneration::shrink(size_t bytes) { - assert_correct_size_change_locking(); - - size_t size = ReservedSpace::page_align_size_down(bytes); - if (size == 0) { - return; - } - - // Shrink committed space - _virtual_space.shrink_by(size); - // Shrink space; this also shrinks the space's BOT - space()->set_end((HeapWord*) _virtual_space.high()); - size_t new_word_size = heap_word_size(space()->capacity()); - // Shrink the shared block offset array - _bts->resize(new_word_size); - MemRegion mr(space()->bottom(), new_word_size); - // Shrink the card table - GenCollectedHeap::heap()->rem_set()->resize_covered_region(mr); - - size_t new_mem_size = _virtual_space.committed_size(); - size_t old_mem_size = new_mem_size + size; - log_trace(gc, heap)("Shrinking %s from " SIZE_FORMAT "K to " SIZE_FORMAT "K", - name(), old_mem_size/K, new_mem_size/K); -} - -// Objects in this generation may have moved, invalidate this -// generation's cards. -void CardGeneration::invalidate_remembered_set() { - _rs->invalidate(used_region()); -} - -void CardGeneration::compute_new_size() { - assert(_shrink_factor <= 100, "invalid shrink factor"); - size_t current_shrink_factor = _shrink_factor; - if (ShrinkHeapInSteps) { - // Always reset '_shrink_factor' if the heap is shrunk in steps. - // If we shrink the heap in this iteration, '_shrink_factor' will - // be recomputed based on the old value further down in this fuction. - _shrink_factor = 0; - } - - // We don't have floating point command-line arguments - // Note: argument processing ensures that MinHeapFreeRatio < 100. - const double minimum_free_percentage = MinHeapFreeRatio / 100.0; - const double maximum_used_percentage = 1.0 - minimum_free_percentage; - - // Compute some numbers about the state of the heap. - const size_t used_after_gc = used(); - const size_t capacity_after_gc = capacity(); - - const double min_tmp = used_after_gc / maximum_used_percentage; - size_t minimum_desired_capacity = (size_t)MIN2(min_tmp, double(max_uintx)); - // Don't shrink less than the initial generation size - minimum_desired_capacity = MAX2(minimum_desired_capacity, initial_size()); - assert(used_after_gc <= minimum_desired_capacity, "sanity check"); - - const size_t free_after_gc = free(); - const double free_percentage = ((double)free_after_gc) / capacity_after_gc; - log_trace(gc, heap)("CardGeneration::compute_new_size:"); - log_trace(gc, heap)(" minimum_free_percentage: %6.2f maximum_used_percentage: %6.2f", - minimum_free_percentage, - maximum_used_percentage); - log_trace(gc, heap)(" free_after_gc : %6.1fK used_after_gc : %6.1fK capacity_after_gc : %6.1fK", - free_after_gc / (double) K, - used_after_gc / (double) K, - capacity_after_gc / (double) K); - log_trace(gc, heap)(" free_percentage: %6.2f", free_percentage); - - if (capacity_after_gc < minimum_desired_capacity) { - // If we have less free space than we want then expand - size_t expand_bytes = minimum_desired_capacity - capacity_after_gc; - // Don't expand unless it's significant - if (expand_bytes >= _min_heap_delta_bytes) { - expand(expand_bytes, 0); // safe if expansion fails - } - log_trace(gc, heap)(" expanding: minimum_desired_capacity: %6.1fK expand_bytes: %6.1fK _min_heap_delta_bytes: %6.1fK", - minimum_desired_capacity / (double) K, - expand_bytes / (double) K, - _min_heap_delta_bytes / (double) K); - return; - } - - // No expansion, now see if we want to shrink - size_t shrink_bytes = 0; - // We would never want to shrink more than this - size_t max_shrink_bytes = capacity_after_gc - minimum_desired_capacity; - - if (MaxHeapFreeRatio < 100) { - const double maximum_free_percentage = MaxHeapFreeRatio / 100.0; - const double minimum_used_percentage = 1.0 - maximum_free_percentage; - const double max_tmp = used_after_gc / minimum_used_percentage; - size_t maximum_desired_capacity = (size_t)MIN2(max_tmp, double(max_uintx)); - maximum_desired_capacity = MAX2(maximum_desired_capacity, initial_size()); - log_trace(gc, heap)(" maximum_free_percentage: %6.2f minimum_used_percentage: %6.2f", - maximum_free_percentage, minimum_used_percentage); - log_trace(gc, heap)(" _capacity_at_prologue: %6.1fK minimum_desired_capacity: %6.1fK maximum_desired_capacity: %6.1fK", - _capacity_at_prologue / (double) K, - minimum_desired_capacity / (double) K, - maximum_desired_capacity / (double) K); - assert(minimum_desired_capacity <= maximum_desired_capacity, - "sanity check"); - - if (capacity_after_gc > maximum_desired_capacity) { - // Capacity too large, compute shrinking size - shrink_bytes = capacity_after_gc - maximum_desired_capacity; - if (ShrinkHeapInSteps) { - // If ShrinkHeapInSteps is true (the default), - // we don't want to shrink all the way back to initSize if people call - // System.gc(), because some programs do that between "phases" and then - // we'd just have to grow the heap up again for the next phase. So we - // damp the shrinking: 0% on the first call, 10% on the second call, 40% - // on the third call, and 100% by the fourth call. But if we recompute - // size without shrinking, it goes back to 0%. - shrink_bytes = shrink_bytes / 100 * current_shrink_factor; - if (current_shrink_factor == 0) { - _shrink_factor = 10; - } else { - _shrink_factor = MIN2(current_shrink_factor * 4, (size_t) 100); - } - } - assert(shrink_bytes <= max_shrink_bytes, "invalid shrink size"); - log_trace(gc, heap)(" shrinking: initSize: %.1fK maximum_desired_capacity: %.1fK", - initial_size() / (double) K, maximum_desired_capacity / (double) K); - log_trace(gc, heap)(" shrink_bytes: %.1fK current_shrink_factor: " SIZE_FORMAT " new shrink factor: " SIZE_FORMAT " _min_heap_delta_bytes: %.1fK", - shrink_bytes / (double) K, - current_shrink_factor, - _shrink_factor, - _min_heap_delta_bytes / (double) K); - } - } - - if (capacity_after_gc > _capacity_at_prologue) { - // We might have expanded for promotions, in which case we might want to - // take back that expansion if there's room after GC. That keeps us from - // stretching the heap with promotions when there's plenty of room. - size_t expansion_for_promotion = capacity_after_gc - _capacity_at_prologue; - expansion_for_promotion = MIN2(expansion_for_promotion, max_shrink_bytes); - // We have two shrinking computations, take the largest - shrink_bytes = MAX2(shrink_bytes, expansion_for_promotion); - assert(shrink_bytes <= max_shrink_bytes, "invalid shrink size"); - log_trace(gc, heap)(" aggressive shrinking: _capacity_at_prologue: %.1fK capacity_after_gc: %.1fK expansion_for_promotion: %.1fK shrink_bytes: %.1fK", - capacity_after_gc / (double) K, - _capacity_at_prologue / (double) K, - expansion_for_promotion / (double) K, - shrink_bytes / (double) K); - } - // Don't shrink unless it's significant - if (shrink_bytes >= _min_heap_delta_bytes) { - shrink(shrink_bytes); - } -} - -void CardGeneration::space_iterate(SpaceClosure* blk, - bool usedOnly) { - blk->do_space(space()); -} - -void CardGeneration::younger_refs_iterate(OopIterateClosure* blk) { - // Apply "cl->do_oop" to (the address of) (exactly) all the ref fields in - // "sp" that point into the young generation. - // The iteration is only over objects allocated at the start of the - // iterations; objects allocated as a result of applying the closure are - // not included. - - HeapWord* gen_boundary = reserved().start(); - _rs->younger_refs_in_space_iterate(space(), gen_boundary, blk); -} diff --git a/src/hotspot/share/gc/shared/cardGeneration.hpp b/src/hotspot/share/gc/shared/cardGeneration.hpp deleted file mode 100644 index 084737a61466d7adc3748dbc577a3dca1ad825a1..0000000000000000000000000000000000000000 --- a/src/hotspot/share/gc/shared/cardGeneration.hpp +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Copyright (c) 2014, 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. - * - */ - -#ifndef SHARE_GC_SHARED_CARDGENERATION_HPP -#define SHARE_GC_SHARED_CARDGENERATION_HPP - -// Class CardGeneration is a generation that is covered by a card table, -// and uses a card-size block-offset array to implement block_start. - -#include "gc/shared/generation.hpp" - -class BlockOffsetSharedArray; -class CardTableRS; -class CompactibleSpace; - -class CardGeneration: public Generation { - friend class VMStructs; - protected: - // This is shared with other generations. - CardTableRS* _rs; - // This is local to this generation. - BlockOffsetSharedArray* _bts; - - // Current shrinking effect: this damps shrinking when the heap gets empty. - size_t _shrink_factor; - - size_t _min_heap_delta_bytes; // Minimum amount to expand. - - // Some statistics from before gc started. - // These are gathered in the gc_prologue (and should_collect) - // to control growing/shrinking policy in spite of promotions. - size_t _capacity_at_prologue; - size_t _used_at_prologue; - - CardGeneration(ReservedSpace rs, size_t initial_byte_size, CardTableRS* remset); - - virtual void assert_correct_size_change_locking() = 0; - - virtual CompactibleSpace* space() const = 0; - - public: - - // Attempt to expand the generation by "bytes". Expand by at a - // minimum "expand_bytes". Return true if some amount (not - // necessarily the full "bytes") was done. - virtual bool expand(size_t bytes, size_t expand_bytes); - - // Shrink generation with specified size - virtual void shrink(size_t bytes); - - virtual void compute_new_size(); - - virtual void invalidate_remembered_set(); - - // Grow generation with specified size (returns false if unable to grow) - bool grow_by(size_t bytes); - // Grow generation to reserved size. - bool grow_to_reserved(); - - size_t capacity() const; - size_t used() const; - size_t free() const; - MemRegion used_region() const; - - void space_iterate(SpaceClosure* blk, bool usedOnly = false); - - void younger_refs_iterate(OopIterateClosure* blk); - - bool is_in(const void* p) const; - - CompactibleSpace* first_compaction_space() const; -}; - -#endif // SHARE_GC_SHARED_CARDGENERATION_HPP diff --git a/src/hotspot/share/gc/shared/cardTable.cpp b/src/hotspot/share/gc/shared/cardTable.cpp index b7f7ab81c36d208308826806cd06e328f560cba5..cd991af6211b6a100aa13f38e1af14d60974540f 100644 --- a/src/hotspot/share/gc/shared/cardTable.cpp +++ b/src/hotspot/share/gc/shared/cardTable.cpp @@ -385,32 +385,6 @@ void CardTable::dirty(MemRegion mr) { memset(first, dirty_card, last-first); } -// Unlike several other card table methods, dirty_card_iterate() -// iterates over dirty cards ranges in increasing address order. -void CardTable::dirty_card_iterate(MemRegion mr, MemRegionClosure* cl) { - for (int i = 0; i < _cur_covered_regions; i++) { - MemRegion mri = mr.intersection(_covered[i]); - if (!mri.is_empty()) { - CardValue *cur_entry, *next_entry, *limit; - for (cur_entry = byte_for(mri.start()), limit = byte_for(mri.last()); - cur_entry <= limit; - cur_entry = next_entry) { - next_entry = cur_entry + 1; - if (*cur_entry == dirty_card) { - size_t dirty_cards; - // Accumulate maximal dirty card range, starting at cur_entry - for (dirty_cards = 1; - next_entry <= limit && *next_entry == dirty_card; - dirty_cards++, next_entry++); - MemRegion cur_cards(addr_for(cur_entry), - dirty_cards*_card_size_in_words); - cl->do_MemRegion(cur_cards); - } - } - } - } -} - MemRegion CardTable::dirty_card_range_after_reset(MemRegion mr, bool reset, int reset_val) { diff --git a/src/hotspot/share/gc/shared/cardTable.hpp b/src/hotspot/share/gc/shared/cardTable.hpp index ca6d1ef51dda49a08b03e01e2ce838b1009385d7..7b74e74d82be44fee9feac25714a271a8a8a330c 100644 --- a/src/hotspot/share/gc/shared/cardTable.hpp +++ b/src/hotspot/share/gc/shared/cardTable.hpp @@ -218,10 +218,6 @@ public: static uintx ct_max_alignment_constraint(); - // Apply closure "cl" to the dirty cards containing some part of - // MemRegion "mr". - void dirty_card_iterate(MemRegion mr, MemRegionClosure* cl); - // Return the MemRegion corresponding to the first maximal run // of dirty cards lying completely within MemRegion mr. // If reset is "true", then sets those card table entries to the given diff --git a/src/hotspot/share/gc/shared/collectedHeap.cpp b/src/hotspot/share/gc/shared/collectedHeap.cpp index f9ad0759b428141c89fa8b7fa38198cba0a3347a..eb3213d12df1b4ea3cd15ef6e62268637673e837 100644 --- a/src/hotspot/share/gc/shared/collectedHeap.cpp +++ b/src/hotspot/share/gc/shared/collectedHeap.cpp @@ -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 @@ -417,6 +417,11 @@ size_t CollectedHeap::filler_array_min_size() { return align_object_size(filler_array_hdr_size()); // align to MinObjAlignment } +void CollectedHeap::zap_filler_array_with(HeapWord* start, size_t words, juint value) { + Copy::fill_to_words(start + filler_array_hdr_size(), + words - filler_array_hdr_size(), value); +} + #ifdef ASSERT void CollectedHeap::fill_args_check(HeapWord* start, size_t words) { @@ -427,8 +432,7 @@ void CollectedHeap::fill_args_check(HeapWord* start, size_t words) void CollectedHeap::zap_filler_array(HeapWord* start, size_t words, bool zap) { if (ZapFillerObjects && zap) { - Copy::fill_to_words(start + filler_array_hdr_size(), - words - filler_array_hdr_size(), 0XDEAFBABE); + zap_filler_array_with(start, words, 0XDEAFBABE); } } #endif // ASSERT @@ -445,7 +449,13 @@ CollectedHeap::fill_with_array(HeapWord* start, size_t words, bool zap) ObjArrayAllocator allocator(Universe::intArrayKlassObj(), words, (int)len, /* do_zero */ false); allocator.initialize(start); - DEBUG_ONLY(zap_filler_array(start, words, zap);) + if (DumpSharedSpaces) { + // This array is written into the CDS archive. Make sure it + // has deterministic contents. + zap_filler_array_with(start, words, 0); + } else { + DEBUG_ONLY(zap_filler_array(start, words, zap);) + } } void diff --git a/src/hotspot/share/gc/shared/collectedHeap.hpp b/src/hotspot/share/gc/shared/collectedHeap.hpp index 89cca6777d64a8f3803b384f720942d877329f61..fd6427fee6019cbac528556649d5b5f466e5bb2b 100644 --- a/src/hotspot/share/gc/shared/collectedHeap.hpp +++ b/src/hotspot/share/gc/shared/collectedHeap.hpp @@ -157,6 +157,7 @@ class CollectedHeap : public CHeapObj { static inline size_t filler_array_hdr_size(); static inline size_t filler_array_min_size(); + static inline void zap_filler_array_with(HeapWord* start, size_t words, juint value); DEBUG_ONLY(static void fill_args_check(HeapWord* start, size_t words);) DEBUG_ONLY(static void zap_filler_array(HeapWord* start, size_t words, bool zap = true);) diff --git a/src/hotspot/share/gc/shared/freeListAllocator.cpp b/src/hotspot/share/gc/shared/freeListAllocator.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f616e33691cf37f66dc0c9feb42fe7391ec7e332 --- /dev/null +++ b/src/hotspot/share/gc/shared/freeListAllocator.cpp @@ -0,0 +1,213 @@ +/* + * 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 "precompiled.hpp" +#include "gc/shared/freeListAllocator.hpp" +#include "logging/log.hpp" +#include "utilities/globalCounter.inline.hpp" + +FreeListAllocator::NodeList::NodeList() : + _head(nullptr), _tail(nullptr), _entry_count(0) {} + +FreeListAllocator::NodeList::NodeList(FreeNode* head, FreeNode* tail, size_t entry_count) : + _head(head), _tail(tail), _entry_count(entry_count) +{ + assert((_head == nullptr) == (_tail == nullptr), "invariant"); + assert((_head == nullptr) == (_entry_count == 0), "invariant"); +} + +FreeListAllocator::PendingList::PendingList() : + _tail(nullptr), _head(nullptr), _count(0) {} + +size_t FreeListAllocator::PendingList::add(FreeNode* node) { + assert(node->next() == nullptr, "precondition"); + FreeNode* old_head = Atomic::xchg(&_head, node); + if (old_head != nullptr) { + node->set_next(old_head); + } else { + assert(_tail == nullptr, "invariant"); + _tail = node; + } + return Atomic::add(&_count, size_t(1)); +} + +typename FreeListAllocator::NodeList FreeListAllocator::PendingList::take_all() { + NodeList result{Atomic::load(&_head), _tail, Atomic::load(&_count)}; + Atomic::store(&_head, (FreeNode*)nullptr); + _tail = nullptr; + Atomic::store(&_count, size_t(0)); + return result; +} + +size_t FreeListAllocator::PendingList::count() const { + return Atomic::load(&_count); +} + +FreeListAllocator::FreeListAllocator(const char* name, FreeListConfig* config) : + _config(config), + _free_count(0), + _free_list(), + _transfer_lock(false), + _active_pending_list(0), + _pending_lists() +{ + strncpy(_name, name, sizeof(_name) - 1); + _name[sizeof(_name) - 1] = '\0'; +} + +void FreeListAllocator::delete_list(FreeNode* list) { + while (list != nullptr) { + FreeNode* next = list->next(); + list->~FreeNode(); + _config->deallocate(list); + list = next; + } +} + +FreeListAllocator::~FreeListAllocator() { + uint index = Atomic::load(&_active_pending_list); + NodeList pending_list = _pending_lists[index].take_all(); + delete_list(Atomic::load(&pending_list._head)); + delete_list(_free_list.pop_all()); +} + +// Drop existing nodes and reset all counters +void FreeListAllocator::reset() { + uint index = Atomic::load(&_active_pending_list); + _pending_lists[index].take_all(); + _free_list.pop_all(); + _free_count = 0; +} + +size_t FreeListAllocator::free_count() const { + return Atomic::load(&_free_count); +} + +size_t FreeListAllocator::pending_count() const { + uint index = Atomic::load(&_active_pending_list); + return _pending_lists[index].count();; +} + +// To solve the ABA problem, popping a node from the _free_list is performed within +// a GlobalCounter critical section, and pushing nodes onto the _free_list is done +// after a GlobalCounter synchronization associated with the nodes to be pushed. +void* FreeListAllocator::allocate() { + FreeNode* node = nullptr; + if (free_count() > 0) { + // Protect against ABA; see release(). + GlobalCounter::CriticalSection cs(Thread::current()); + node = _free_list.pop(); + } + + if (node != nullptr) { + node->~FreeNode(); + // Decrement count after getting buffer from free list. This, along + // with incrementing count before adding to free list, ensures count + // never underflows. + size_t count = Atomic::sub(&_free_count, 1u); + assert((count + 1) != 0, "_free_count underflow"); + return node; + } else { + return _config->allocate(); + } +} + +// The release synchronizes on the critical sections before adding to +// the _free_list. But we don't want to make every release have to do a +// synchronize. Instead, we initially place released nodes on the pending list, +// and transfer them to the _free_list in batches. Only one transfer at a time is +// permitted, with a lock bit to control access to that phase. While a transfer +// is in progress, other threads might be adding other nodes to the pending list, +// to be dealt with by some later transfer. +void FreeListAllocator::release(void* free_node) { + assert(free_node != nullptr, "precondition"); + assert(is_aligned(free_node, sizeof(FreeNode)), "Unaligned addr " PTR_FORMAT, p2i(free_node)); + FreeNode* node = ::new (free_node) FreeNode(); + + // The pending list is double-buffered. Add node to the currently active + // pending list, within a critical section so a transfer will wait until + // we're done with what might be the pending list to be transferred. + { + GlobalCounter::CriticalSection cs(Thread::current()); + uint index = Atomic::load_acquire(&_active_pending_list); + size_t count = _pending_lists[index].add(node); + if (count <= _config->transfer_threshold()) return; + } + // Attempt transfer when number pending exceeds the transfer threshold. + try_transfer_pending(); +} + +// Try to transfer nodes from the pending list to _free_list, with a +// synchronization delay for any in-progress pops from the _free_list, +// to solve ABA there. Return true if performed a (possibly empty) +// transfer, false if blocked from doing so by some other thread's +// in-progress transfer. +bool FreeListAllocator::try_transfer_pending() { + // Attempt to claim the lock. + if (Atomic::load(&_transfer_lock) || // Skip CAS if likely to fail. + Atomic::cmpxchg(&_transfer_lock, false, true)) { + return false; + } + // Have the lock; perform the transfer. + + // Change which pending list is active. Don't need an atomic RMW since + // we have the lock and we're the only writer. + uint index = Atomic::load(&_active_pending_list); + uint new_active = (index + 1) % ARRAY_SIZE(_pending_lists); + Atomic::release_store(&_active_pending_list, new_active); + + // Wait for all critical sections in the buffer life-cycle to complete. + // This includes _free_list pops and adding to the now inactive pending + // list. + GlobalCounter::write_synchronize(); + + // Transfer the inactive pending list to _free_list. + NodeList transfer_list = _pending_lists[index].take_all(); + size_t count = transfer_list._entry_count; + if (count > 0) { + // Update count first so no underflow in allocate(). + Atomic::add(&_free_count, count); + _free_list.prepend(*transfer_list._head, *transfer_list._tail); + log_trace(gc, freelist) + ("Transferred %s pending to free: %zu", name(), count); + } + Atomic::release_store(&_transfer_lock, false); + return true; +} + +size_t FreeListAllocator::reduce_free_list(size_t remove_goal) { + try_transfer_pending(); + size_t removed = 0; + for ( ; removed < remove_goal; ++removed) { + FreeNode* node = _free_list.pop(); + if (node == nullptr) break; + node->~FreeNode(); + _config->deallocate(node); + } + size_t new_count = Atomic::sub(&_free_count, removed); + log_debug(gc, freelist) + ("Reduced %s free list by " SIZE_FORMAT " to " SIZE_FORMAT, + name(), removed, new_count); + return removed; +} diff --git a/src/hotspot/share/gc/shared/freeListAllocator.hpp b/src/hotspot/share/gc/shared/freeListAllocator.hpp new file mode 100644 index 0000000000000000000000000000000000000000..8f4aba0ed03ab56196eeb76e7c7fffd51a05a621 --- /dev/null +++ b/src/hotspot/share/gc/shared/freeListAllocator.hpp @@ -0,0 +1,161 @@ +/* + * 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 SHARE_GC_SHARED_FREELISTALLOCATOR_HPP +#define SHARE_GC_SHARED_FREELISTALLOCATOR_HPP + +#include "memory/allocation.hpp" +#include "memory/padded.hpp" +#include "runtime/atomic.hpp" +#include "utilities/globalDefinitions.hpp" +#include "utilities/lockFreeStack.hpp" + +class FreeListConfig { + // Desired minimum transfer batch size. There is relatively little + // importance to the specific number. It shouldn't be too big, else + // we're wasting space when the release rate is low. If the release + // rate is high, we might accumulate more than this before being + // able to start a new transfer, but that's okay. + const size_t _transfer_threshold; +protected: + ~FreeListConfig() = default; +public: + explicit FreeListConfig(size_t threshold = 10) : _transfer_threshold(threshold) {} + + size_t transfer_threshold() { return _transfer_threshold; } + + virtual void* allocate() = 0; + + virtual void deallocate(void* node) = 0; +}; + +// Allocation is based on a lock-free list of nodes. To reduce synchronization +// overhead on the free list between allocation and release calls, the released +// nodes are first placed on a pending list, then transferred to the free list in +// batches. While on the pending list, the nodes are not available for allocation. +// The allocator uses allocation options specified by an instance of +// FreeListConfig. The FreeListConfig includes an allocation method to use in case +// the free list is empty and a deallocation method used to deallocate nodes in +// the free list. Additionally, the FreeListConfig configures the threshold used +// as a minimum batch size for transferring released nodes from the pending list +// to the free list making them available for re-allocation. +class FreeListAllocator { + struct FreeNode { + FreeNode* volatile _next; + + FreeNode() : _next (nullptr) { } + + FreeNode* next() { return Atomic::load(&_next); } + + FreeNode* volatile* next_addr() { return &_next; } + + void set_next(FreeNode* next) { Atomic::store(&_next, next); } + }; + + struct NodeList { + FreeNode* _head; // First node in list or nullptr if empty. + FreeNode* _tail; // Last node in list or nullptr if empty. + size_t _entry_count; // Sum of entries in nodes in list. + + NodeList(); + + NodeList(FreeNode* head, FreeNode* tail, size_t entry_count); + }; + + class PendingList { + FreeNode* _tail; + FreeNode* volatile _head; + volatile size_t _count; + + NONCOPYABLE(PendingList); + + public: + PendingList(); + ~PendingList() = default; + + // Add node to the list. Returns the number of nodes in the list. + // Thread-safe against concurrent add operations. + size_t add(FreeNode* node); + + size_t count() const; + + // Return the nodes in the list, leaving the list empty. + // Not thread-safe. + NodeList take_all(); + }; + + static FreeNode* volatile* next_ptr(FreeNode& node) { return node.next_addr(); } + typedef LockFreeStack Stack; + + FreeListConfig* _config; + char _name[DEFAULT_CACHE_LINE_SIZE - sizeof(FreeListConfig*)]; // Use name as padding. + +#define DECLARE_PADDED_MEMBER(Id, Type, Name) \ + Type Name; DEFINE_PAD_MINUS_SIZE(Id, DEFAULT_CACHE_LINE_SIZE, sizeof(Type)) + DECLARE_PADDED_MEMBER(1, volatile size_t, _free_count); + DECLARE_PADDED_MEMBER(2, Stack, _free_list); + DECLARE_PADDED_MEMBER(3, volatile bool, _transfer_lock); +#undef DECLARE_PADDED_MEMBER + + volatile uint _active_pending_list; + PendingList _pending_lists[2]; + + void delete_list(FreeNode* list); + + NONCOPYABLE(FreeListAllocator); + +public: + FreeListAllocator(const char* name, FreeListConfig* config); + + const char* name() const { return _name; } + + ~FreeListAllocator(); + + size_t free_count() const; + size_t pending_count() const; + + void* allocate(); + void release(void* node); + + // Free nodes in the allocator could have been allocated out of an arena. + // Therefore, the nodes can be freed at once when entire arena is discarded + // without running destructors for the individual nodes. In such cases, reset + // method should be called before the ~FreeListAllocator(). Calling the reset + // method on nodes not managed by an arena will leak the memory by just dropping + // the nodes to the floor. + void reset(); + bool try_transfer_pending(); + + size_t mem_size() const { + return sizeof(*this); + } + + // Deallocate some of the available nodes in the free_list. + // remove_goal is the target number to remove. Returns the number + // actually deallocated, which may be less than the goal if there + // were fewer available. + size_t reduce_free_list(size_t remove_goal); +}; + +#endif // SHARE_GC_SHARED_FREELISTALLOCATOR_HPP diff --git a/src/hotspot/share/gc/shared/generation.hpp b/src/hotspot/share/gc/shared/generation.hpp index b9183ec28987b5b3c1c63945acdec9decb39c417..36740cc4039cb192dbe3aa0c0849fc5384342cf9 100644 --- a/src/hotspot/share/gc/shared/generation.hpp +++ b/src/hotspot/share/gc/shared/generation.hpp @@ -41,8 +41,7 @@ // // Generation - abstract base class // - DefNewGeneration - allocation area (copy collected) -// - CardGeneration - abstract class adding offset array behavior -// - TenuredGeneration - tenured (old object) space (markSweepCompact) +// - TenuredGeneration - tenured (old object) space (markSweepCompact) // // The system configuration currently allowed is: // diff --git a/src/hotspot/share/gc/shared/ptrQueue.cpp b/src/hotspot/share/gc/shared/ptrQueue.cpp index 0a95e36de2b73ae6b7de7eb4974b568985e055f8..e6f24df4d2e19127fa839ce9f8888e8953e31905 100644 --- a/src/hotspot/share/gc/shared/ptrQueue.cpp +++ b/src/hotspot/share/gc/shared/ptrQueue.cpp @@ -24,14 +24,7 @@ #include "precompiled.hpp" #include "gc/shared/ptrQueue.hpp" -#include "logging/log.hpp" -#include "memory/allocation.hpp" #include "memory/allocation.inline.hpp" -#include "runtime/atomic.hpp" -#include "runtime/mutex.hpp" -#include "runtime/mutexLocker.hpp" -#include "runtime/thread.inline.hpp" -#include "utilities/globalCounter.inline.hpp" #include @@ -45,178 +38,42 @@ PtrQueue::~PtrQueue() { assert(_buf == NULL, "queue must be flushed before delete"); } -BufferNode* BufferNode::allocate(size_t size) { - size_t byte_size = size * sizeof(void*); - void* data = NEW_C_HEAP_ARRAY(char, buffer_offset() + byte_size, mtGC); - return new (data) BufferNode; -} - -void BufferNode::deallocate(BufferNode* node) { - node->~BufferNode(); - FREE_C_HEAP_ARRAY(char, node); -} - -BufferNode::Allocator::PendingList::PendingList() : - _tail(nullptr), _head(nullptr), _count(0) {} +BufferNode::AllocatorConfig::AllocatorConfig(size_t size) : _buffer_size(size) {} -BufferNode::Allocator::PendingList::~PendingList() { - delete_list(Atomic::load(&_head)); +void* BufferNode::AllocatorConfig::allocate() { + size_t byte_size = _buffer_size * sizeof(void*); + return NEW_C_HEAP_ARRAY(char, buffer_offset() + byte_size, mtGC); } -size_t BufferNode::Allocator::PendingList::add(BufferNode* node) { - assert(node->next() == nullptr, "precondition"); - BufferNode* old_head = Atomic::xchg(&_head, node); - if (old_head != nullptr) { - node->set_next(old_head); - } else { - assert(_tail == nullptr, "invariant"); - _tail = node; - } - return Atomic::add(&_count, size_t(1)); -} - -BufferNodeList BufferNode::Allocator::PendingList::take_all() { - BufferNodeList result{Atomic::load(&_head), _tail, Atomic::load(&_count)}; - Atomic::store(&_head, (BufferNode*)nullptr); - _tail = nullptr; - Atomic::store(&_count, size_t(0)); - return result; +void BufferNode::AllocatorConfig::deallocate(void* node) { + assert(node != nullptr, "precondition"); + FREE_C_HEAP_ARRAY(char, node); } BufferNode::Allocator::Allocator(const char* name, size_t buffer_size) : - _buffer_size(buffer_size), - _pending_lists(), - _active_pending_list(0), - _free_list(), - _free_count(0), - _transfer_lock(false) + _config(buffer_size), + _free_list(name, &_config) { - strncpy(_name, name, sizeof(_name) - 1); - _name[sizeof(_name) - 1] = '\0'; -} -BufferNode::Allocator::~Allocator() { - delete_list(_free_list.pop_all()); -} - -void BufferNode::Allocator::delete_list(BufferNode* list) { - while (list != NULL) { - BufferNode* next = list->next(); - DEBUG_ONLY(list->set_next(NULL);) - BufferNode::deallocate(list); - list = next; - } } size_t BufferNode::Allocator::free_count() const { - return Atomic::load(&_free_count); + return _free_list.free_count(); } BufferNode* BufferNode::Allocator::allocate() { - BufferNode* node; - { - // Protect against ABA; see release(). - GlobalCounter::CriticalSection cs(Thread::current()); - node = _free_list.pop(); - } - if (node == NULL) { - node = BufferNode::allocate(_buffer_size); - } else { - // Decrement count after getting buffer from free list. This, along - // with incrementing count before adding to free list, ensures count - // never underflows. - size_t count = Atomic::sub(&_free_count, 1u); - assert((count + 1) != 0, "_free_count underflow"); - } - return node; + return ::new (_free_list.allocate()) BufferNode(); } -// To solve the ABA problem for lock-free stack pop, allocate does the -// pop inside a critical section, and release synchronizes on the -// critical sections before adding to the _free_list. But we don't -// want to make every release have to do a synchronize. Instead, we -// initially place released nodes on the pending list, and transfer -// them to the _free_list in batches. Only one transfer at a time is -// permitted, with a lock bit to control access to that phase. While -// a transfer is in progress, other threads might be adding other nodes -// to the pending list, to be dealt with by some later transfer. void BufferNode::Allocator::release(BufferNode* node) { assert(node != NULL, "precondition"); assert(node->next() == NULL, "precondition"); - - // Desired minimum transfer batch size. There is relatively little - // importance to the specific number. It shouldn't be too big, else - // we're wasting space when the release rate is low. If the release - // rate is high, we might accumulate more than this before being - // able to start a new transfer, but that's okay. Also note that - // the allocation rate and the release rate are going to be fairly - // similar, due to how the buffers are used. - const size_t trigger_transfer = 10; - - // The pending list is double-buffered. Add node to the currently active - // pending list, within a critical section so a transfer will wait until - // we're done with what might be the pending list to be transferred. - { - GlobalCounter::CriticalSection cs(Thread::current()); - uint index = Atomic::load_acquire(&_active_pending_list); - size_t count = _pending_lists[index].add(node); - if (count <= trigger_transfer) return; - } - // Attempt transfer when number pending exceeds the transfer threshold. - try_transfer_pending(); -} - -// Try to transfer nodes from the pending list to _free_list, with a -// synchronization delay for any in-progress pops from the _free_list, -// to solve ABA there. Return true if performed a (possibly empty) -// transfer, false if blocked from doing so by some other thread's -// in-progress transfer. -bool BufferNode::Allocator::try_transfer_pending() { - // Attempt to claim the lock. - if (Atomic::load(&_transfer_lock) || // Skip CAS if likely to fail. - Atomic::cmpxchg(&_transfer_lock, false, true)) { - return false; - } - // Have the lock; perform the transfer. - - // Change which pending list is active. Don't need an atomic RMW since - // we have the lock and we're the only writer. - uint index = Atomic::load(&_active_pending_list); - uint new_active = (index + 1) % ARRAY_SIZE(_pending_lists); - Atomic::release_store(&_active_pending_list, new_active); - - // Wait for all critical sections in the buffer life-cycle to complete. - // This includes _free_list pops and adding to the now inactive pending - // list. - GlobalCounter::write_synchronize(); - - // Transfer the inactive pending list to _free_list. - BufferNodeList transfer_list = _pending_lists[index].take_all(); - size_t count = transfer_list._entry_count; - if (count > 0) { - // Update count first so no underflow in allocate(). - Atomic::add(&_free_count, count); - _free_list.prepend(*transfer_list._head, *transfer_list._tail); - log_trace(gc, ptrqueue, freelist) - ("Transferred %s pending to free: %zu", name(), count); - } - Atomic::release_store(&_transfer_lock, false); - return true; + node->~BufferNode(); + _free_list.release(node); } size_t BufferNode::Allocator::reduce_free_list(size_t remove_goal) { - try_transfer_pending(); - size_t removed = 0; - for ( ; removed < remove_goal; ++removed) { - BufferNode* node = _free_list.pop(); - if (node == NULL) break; - BufferNode::deallocate(node); - } - size_t new_count = Atomic::sub(&_free_count, removed); - log_debug(gc, ptrqueue, freelist) - ("Reduced %s free list by " SIZE_FORMAT " to " SIZE_FORMAT, - name(), removed, new_count); - return removed; + return _free_list.reduce_free_list(remove_goal); } PtrQueueSet::PtrQueueSet(BufferNode::Allocator* allocator) : diff --git a/src/hotspot/share/gc/shared/ptrQueue.hpp b/src/hotspot/share/gc/shared/ptrQueue.hpp index be07f3e58b35e602c3d97b08dab3ef75e93399a3..844f73941cd1d274637d64e86259934f7bbc67f4 100644 --- a/src/hotspot/share/gc/shared/ptrQueue.hpp +++ b/src/hotspot/share/gc/shared/ptrQueue.hpp @@ -25,7 +25,7 @@ #ifndef SHARE_GC_SHARED_PTRQUEUE_HPP #define SHARE_GC_SHARED_PTRQUEUE_HPP -#include "gc/shared/bufferNodeList.hpp" +#include "gc/shared/freeListAllocator.hpp" #include "memory/padded.hpp" #include "utilities/align.hpp" #include "utilities/debug.hpp" @@ -132,12 +132,6 @@ class BufferNode { return offset_of(BufferNode, _buffer); } - // Allocate a new BufferNode with the "buffer" having size elements. - static BufferNode* allocate(size_t size); - - // Free a BufferNode. - static void deallocate(BufferNode* node); - public: static BufferNode* volatile* next_ptr(BufferNode& bn) { return &bn._next; } typedef LockFreeStack Stack; @@ -163,70 +157,48 @@ public: reinterpret_cast(node) + buffer_offset()); } + class AllocatorConfig; class Allocator; // Free-list based allocator. class TestSupport; // Unit test support. }; -// Allocation is based on a lock-free free list of nodes, linked through -// BufferNode::_next (see BufferNode::Stack). To solve the ABA problem, -// popping a node from the free list is performed within a GlobalCounter -// critical section, and pushing nodes onto the free list is done after -// a GlobalCounter synchronization associated with the nodes to be pushed. -// This is documented behavior so that other parts of the node life-cycle -// can depend on and make use of it too. -class BufferNode::Allocator { - friend class TestSupport; - - // Since we don't expect many instances, and measured >15% speedup - // on stress gtest, padding seems like a good tradeoff here. -#define DECLARE_PADDED_MEMBER(Id, Type, Name) \ - Type Name; DEFINE_PAD_MINUS_SIZE(Id, DEFAULT_CACHE_LINE_SIZE, sizeof(Type)) - - class PendingList { - BufferNode* _tail; - DECLARE_PADDED_MEMBER(1, BufferNode* volatile, _head); - DECLARE_PADDED_MEMBER(2, volatile size_t, _count); - - NONCOPYABLE(PendingList); +// We use BufferNode::AllocatorConfig to set the allocation options for the +// FreeListAllocator. +class BufferNode::AllocatorConfig : public FreeListConfig { + const size_t _buffer_size; +public: + explicit AllocatorConfig(size_t size); - public: - PendingList(); - ~PendingList(); + ~AllocatorConfig() = default; - // Add node to the list. Returns the number of nodes in the list. - // Thread-safe against concurrent add operations. - size_t add(BufferNode* node); + void* allocate() override; - // Return the nodes in the list, leaving the list empty. - // Not thread-safe. - BufferNodeList take_all(); - }; + void deallocate(void* node) override; - const size_t _buffer_size; - char _name[DEFAULT_CACHE_LINE_SIZE - sizeof(size_t)]; // Use name as padding. - PendingList _pending_lists[2]; - DECLARE_PADDED_MEMBER(1, volatile uint, _active_pending_list); - DECLARE_PADDED_MEMBER(2, Stack, _free_list); - DECLARE_PADDED_MEMBER(3, volatile size_t, _free_count); - DECLARE_PADDED_MEMBER(4, volatile bool, _transfer_lock); + size_t buffer_size() const { return _buffer_size; } +}; -#undef DECLARE_PADDED_MEMBER +class BufferNode::Allocator { + friend class TestSupport; - static void delete_list(BufferNode* list); - bool try_transfer_pending(); + AllocatorConfig _config; + FreeListAllocator _free_list; NONCOPYABLE(Allocator); public: Allocator(const char* name, size_t buffer_size); - ~Allocator(); + ~Allocator() = default; - const char* name() const { return _name; } - size_t buffer_size() const { return _buffer_size; } + size_t buffer_size() const { return _config.buffer_size(); } size_t free_count() const; BufferNode* allocate(); void release(BufferNode* node); + // If _free_list has items buffered in the pending list, transfer + // these to make them available for re-allocation. + bool flush_free_list() { return _free_list.try_transfer_pending(); } + // Deallocate some of the available buffers. remove_goal is the target // number to remove. Returns the number actually deallocated, which may // be less than the goal if there were fewer available. diff --git a/src/hotspot/share/gc/shared/taskqueue.hpp b/src/hotspot/share/gc/shared/taskqueue.hpp index d61326bd2fd51e5c9ced6791ba5be3db18eb0616..0c15c38a4d0853281d644de2fed22158c64890c6 100644 --- a/src/hotspot/share/gc/shared/taskqueue.hpp +++ b/src/hotspot/share/gc/shared/taskqueue.hpp @@ -580,7 +580,6 @@ class PartialArrayScanTask { oop _src; public: - PartialArrayScanTask() : _src() {} explicit PartialArrayScanTask(oop src_array) : _src(src_array) {} // Trivially copyable. diff --git a/src/hotspot/share/gc/shared/vmStructs_gc.hpp b/src/hotspot/share/gc/shared/vmStructs_gc.hpp index f9b1c631123fc47fc4b59e9cd5cffb93003f6dc4..d5cf2c15373e0246198a25d160993920c0d4f9b4 100644 --- a/src/hotspot/share/gc/shared/vmStructs_gc.hpp +++ b/src/hotspot/share/gc/shared/vmStructs_gc.hpp @@ -26,7 +26,6 @@ #define SHARE_GC_SHARED_VMSTRUCTS_GC_HPP #include "gc/shared/ageTable.hpp" -#include "gc/shared/cardGeneration.hpp" #include "gc/shared/cardTable.hpp" #include "gc/shared/cardTableRS.hpp" #include "gc/shared/collectedHeap.hpp" @@ -101,11 +100,11 @@ nonstatic_field(BlockOffsetArrayContigSpace, _next_offset_threshold, HeapWord*) \ nonstatic_field(BlockOffsetArrayContigSpace, _next_offset_index, size_t) \ \ - nonstatic_field(CardGeneration, _rs, CardTableRS*) \ - nonstatic_field(CardGeneration, _bts, BlockOffsetSharedArray*) \ - nonstatic_field(CardGeneration, _shrink_factor, size_t) \ - nonstatic_field(CardGeneration, _capacity_at_prologue, size_t) \ - nonstatic_field(CardGeneration, _used_at_prologue, size_t) \ + nonstatic_field(TenuredGeneration, _rs, CardTableRS*) \ + nonstatic_field(TenuredGeneration, _bts, BlockOffsetSharedArray*) \ + nonstatic_field(TenuredGeneration, _shrink_factor, size_t) \ + nonstatic_field(TenuredGeneration, _capacity_at_prologue, size_t) \ + nonstatic_field(TenuredGeneration, _used_at_prologue, size_t) \ \ nonstatic_field(CardTable, _whole_heap, const MemRegion) \ nonstatic_field(CardTable, _guard_index, const size_t) \ @@ -186,7 +185,6 @@ declare_toplevel_type(CollectedHeap) \ declare_type(GenCollectedHeap, CollectedHeap) \ declare_toplevel_type(Generation) \ - declare_type(CardGeneration, Generation) \ declare_toplevel_type(Space) \ declare_type(CompactibleSpace, Space) \ declare_type(ContiguousSpace, CompactibleSpace) \ diff --git a/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp b/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp index f46d94363166e525ade2c572342d443b05a8265e..667808f4efd802c054300269bb17364c68bcc6a5 100644 --- a/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp +++ b/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp @@ -1,5 +1,6 @@ /* * Copyright (c) 2015, 2021, Red Hat, Inc. All rights reserved. + * 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 @@ -566,7 +567,7 @@ void ShenandoahBarrierC2Support::verify(RootNode* root) { { { 2, ShenandoahLoad }, { 3, ShenandoahLoad } }, Op_EncodeISOArray, { { 2, ShenandoahLoad }, { 3, ShenandoahStore } }, - Op_HasNegatives, + Op_CountPositives, { { 2, ShenandoahLoad }, { -1, ShenandoahNone} }, Op_CastP2X, { { 1, ShenandoahLoad }, { -1, ShenandoahNone} }, @@ -706,7 +707,7 @@ Node* ShenandoahBarrierC2Support::no_branches(Node* c, Node* dom, bool allow_one Node* iffproj = NULL; while (c != dom) { Node* next = phase->idom(c); - assert(next->unique_ctrl_out() == c || c->is_Proj() || c->is_Region(), "multiple control flow out but no proj or region?"); + assert(next->unique_ctrl_out_or_null() == c || c->is_Proj() || c->is_Region(), "multiple control flow out but no proj or region?"); if (c->is_Region()) { ResourceMark rm; Unique_Node_List wq; diff --git a/src/hotspot/share/interpreter/templateInterpreter.cpp b/src/hotspot/share/interpreter/templateInterpreter.cpp index 732c12532f7f28e8f6a2f226241e35ff1c7f85e2..322a21b6aa7832e27c0ea2f78704b96a89ede8f3 100644 --- a/src/hotspot/share/interpreter/templateInterpreter.cpp +++ b/src/hotspot/share/interpreter/templateInterpreter.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2022, Oracle and/or its affiliates. All rights reserved. * 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,11 @@ void TemplateInterpreter::initialize_stub() { // allocate interpreter int code_size = InterpreterCodeSize; NOT_PRODUCT(code_size *= 4;) // debug uses extra interpreter code space - _code = new StubQueue(new InterpreterCodeletInterface, code_size, NULL, + // 270+ interpreter codelets are generated and each of them is required to be aligned to + // CodeEntryAlignment twice. So we need additional size due to alignment. + int max_aligned_codelets = 280; + int max_aligned_bytes = max_aligned_codelets * CodeEntryAlignment * 2; + _code = new StubQueue(new InterpreterCodeletInterface, code_size + max_aligned_bytes, NULL, "Interpreter"); } diff --git a/src/hotspot/share/jfr/jni/jfrJavaSupport.cpp b/src/hotspot/share/jfr/jni/jfrJavaSupport.cpp index 5b7891ab45c8ed91077497a656e2cbdd09b6f523..ff15a68753d29a4ccdf01bb2d016ecab785ffc08 100644 --- a/src/hotspot/share/jfr/jni/jfrJavaSupport.cpp +++ b/src/hotspot/share/jfr/jni/jfrJavaSupport.cpp @@ -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 @@ -554,14 +554,16 @@ void JfrJavaSupport::throw_runtime_exception(const char* message, TRAPS) { void JfrJavaSupport::abort(jstring errorMsg, JavaThread* t) { DEBUG_ONLY(check_java_thread_in_vm(t)); - ResourceMark rm(t); - const char* const error_msg = c_str(errorMsg, t); - if (error_msg != NULL) { - log_error(jfr, system)("%s",error_msg); + abort(c_str(errorMsg, t)); +} + +void JfrJavaSupport::abort(const char* error_msg, bool dump_core /* true */) { + if (error_msg != nullptr) { + log_error(jfr, system)("%s", error_msg); } log_error(jfr, system)("%s", "An irrecoverable error in Jfr. Shutting down VM..."); - vm_abort(); + vm_abort(dump_core); } JfrJavaSupport::CAUSE JfrJavaSupport::_cause = JfrJavaSupport::VM_ERROR; diff --git a/src/hotspot/share/jfr/jni/jfrJavaSupport.hpp b/src/hotspot/share/jfr/jni/jfrJavaSupport.hpp index ca97d90dd78a0ef52d7be251bf6ff6f8ce388d80..ee608387c519ce68de5ab259d800b0a8d9b872e2 100644 --- a/src/hotspot/share/jfr/jni/jfrJavaSupport.hpp +++ b/src/hotspot/share/jfr/jni/jfrJavaSupport.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. * 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 @@ class JfrJavaSupport : public AllStatic { // critical static void abort(jstring errorMsg, TRAPS); + static void abort(const char* error_msg, bool dump_core = true); static void uncaught_exception(jthrowable throwable, JavaThread* t); // asserts diff --git a/src/hotspot/share/jfr/leakprofiler/chains/dfsClosure.cpp b/src/hotspot/share/jfr/leakprofiler/chains/dfsClosure.cpp index 8161e172215f4c591cfb9a19624f6da331f06a5e..c6d368a90204282cc6ba74cc9c92fd0c663aac8d 100644 --- a/src/hotspot/share/jfr/leakprofiler/chains/dfsClosure.cpp +++ b/src/hotspot/share/jfr/leakprofiler/chains/dfsClosure.cpp @@ -80,24 +80,23 @@ void DFSClosure::closure_impl(UnifiedOopRef reference, const oop pointee) { if (GranularTimer::is_finished()) { return; } + if (_depth == 0 && _ignore_root_set) { // Root set is already marked, but we want // to continue, so skip is_marked check. assert(_mark_bits->is_marked(pointee), "invariant"); - } else { + _reference_stack[_depth] = reference; + } else { if (_mark_bits->is_marked(pointee)) { return; } + _mark_bits->mark_obj(pointee); + _reference_stack[_depth] = reference; + // is the pointee a sample object? + if (pointee->mark().is_marked()) { + add_chain(); + } } - _reference_stack[_depth] = reference; - _mark_bits->mark_obj(pointee); - assert(_mark_bits->is_marked(pointee), "invariant"); - - // is the pointee a sample object? - if (pointee->mark().is_marked()) { - add_chain(); - } - assert(_max_depth >= 1, "invariant"); if (_depth < _max_depth - 1) { _depth++; diff --git a/src/hotspot/share/jfr/leakprofiler/chains/edgeStore.cpp b/src/hotspot/share/jfr/leakprofiler/chains/edgeStore.cpp index 8ba9409df56406d6fd923efc23e5d6e6336a4e07..c9bee7d1ab6d5147b4710545454be68821df7779 100644 --- a/src/hotspot/share/jfr/leakprofiler/chains/edgeStore.cpp +++ b/src/hotspot/share/jfr/leakprofiler/chains/edgeStore.cpp @@ -234,7 +234,15 @@ static int leak_context_edge_idx(const ObjectSample* sample) { } bool EdgeStore::has_leak_context(const ObjectSample* sample) const { - return leak_context_edge_idx(sample) != 0; + const int idx = leak_context_edge_idx(sample); + if (idx == 0) { + return false; + } + assert(idx > 0, "invariant"); + assert(_leak_context_edges != nullptr, "invariant"); + assert(idx < _leak_context_edges->length(), "invariant"); + assert(_leak_context_edges->at(idx) != nullptr, "invariant"); + return true; } const StoredEdge* EdgeStore::get(const ObjectSample* sample) const { @@ -243,7 +251,10 @@ const StoredEdge* EdgeStore::get(const ObjectSample* sample) const { assert(SafepointSynchronize::is_at_safepoint(), "invariant"); const int idx = leak_context_edge_idx(sample); if (idx > 0) { - return _leak_context_edges->at(idx); + assert(idx < _leak_context_edges->length(), "invariant"); + const StoredEdge* const edge =_leak_context_edges->at(idx); + assert(edge != nullptr, "invariant"); + return edge; } } return get(UnifiedOopRef::encode_in_native(sample->object_addr())); diff --git a/src/hotspot/share/jfr/writers/jfrStreamWriterHost.inline.hpp b/src/hotspot/share/jfr/writers/jfrStreamWriterHost.inline.hpp index 3a7ec2863815958c9ad30a04d5462a272dc4ba95..73404a1aede81be358b65ccecc6fe62a933e6aff 100644 --- a/src/hotspot/share/jfr/writers/jfrStreamWriterHost.inline.hpp +++ b/src/hotspot/share/jfr/writers/jfrStreamWriterHost.inline.hpp @@ -25,8 +25,8 @@ #ifndef SHARE_JFR_WRITERS_JFRSTREAMWRITERHOST_INLINE_HPP #define SHARE_JFR_WRITERS_JFRSTREAMWRITERHOST_INLINE_HPP +#include "jfr/jni/jfrJavaSupport.hpp" #include "jfr/writers/jfrStreamWriterHost.hpp" - #include "runtime/os.hpp" template @@ -77,6 +77,9 @@ inline void StreamWriterHost::write_bytes(const u1* buf, intptr_t l while (len > 0) { const unsigned int nBytes = len > INT_MAX ? INT_MAX : (unsigned int)len; const ssize_t num_written = os::write(_fd, buf, nBytes); + if (errno == ENOSPC) { + JfrJavaSupport::abort("Failed to write to jfr stream because no space left on device", false); + } guarantee(num_written > 0, "Nothing got written, or os::write() failed"); _stream_pos += num_written; len -= num_written; diff --git a/src/hotspot/share/jvmci/vmStructs_jvmci.cpp b/src/hotspot/share/jvmci/vmStructs_jvmci.cpp index 928b59a834f817909df28f8790d2f3cc5240922c..7ed48a79eeb1a9c17ae5d9cbb1a9e3430bfe08f5 100644 --- a/src/hotspot/share/jvmci/vmStructs_jvmci.cpp +++ b/src/hotspot/share/jvmci/vmStructs_jvmci.cpp @@ -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 @@ -312,12 +312,16 @@ static_field(StubRoutines, _base64_encodeBlock, address) \ static_field(StubRoutines, _base64_decodeBlock, address) \ static_field(StubRoutines, _ghash_processBlocks, address) \ + static_field(StubRoutines, _md5_implCompress, address) \ + static_field(StubRoutines, _md5_implCompressMB, address) \ static_field(StubRoutines, _sha1_implCompress, address) \ static_field(StubRoutines, _sha1_implCompressMB, address) \ static_field(StubRoutines, _sha256_implCompress, address) \ static_field(StubRoutines, _sha256_implCompressMB, address) \ static_field(StubRoutines, _sha512_implCompress, address) \ static_field(StubRoutines, _sha512_implCompressMB, address) \ + static_field(StubRoutines, _sha3_implCompress, address) \ + static_field(StubRoutines, _sha3_implCompressMB, address) \ static_field(StubRoutines, _updateBytesCRC32, address) \ static_field(StubRoutines, _crc_table_adr, address) \ static_field(StubRoutines, _crc32c_table_addr, address) \ @@ -738,6 +742,9 @@ #define VM_STRUCTS_CPU(nonstatic_field, static_field, unchecked_nonstatic_field, volatile_nonstatic_field, nonproduct_nonstatic_field, c2_nonstatic_field, unchecked_c1_static_field, unchecked_c2_static_field) \ static_field(VM_Version, _zva_length, int) \ + static_field(StubRoutines::aarch64, _count_positives, address) \ + static_field(StubRoutines::aarch64, _count_positives_long, address) \ + static_field(VM_Version, _rop_protection, bool) \ volatile_nonstatic_field(JavaFrameAnchor, _last_Java_fp, intptr_t*) #define DECLARE_INT_CPU_FEATURE_CONSTANT(id, name, bit) GENERATE_VM_INT_CONSTANT_ENTRY(VM_Version::CPU_##id) diff --git a/src/hotspot/share/memory/heap.hpp b/src/hotspot/share/memory/heap.hpp index 7405cfe5943a46139f25d81ea2b0aa7e58850736..c8cc2ae8dc6d9dc0f1ee85adc686e66e4ccc630e 100644 --- a/src/hotspot/share/memory/heap.hpp +++ b/src/hotspot/share/memory/heap.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -28,6 +28,7 @@ #include "code/codeBlob.hpp" #include "memory/allocation.hpp" #include "memory/virtualspace.hpp" +#include "runtime/atomic.hpp" #include "utilities/macros.hpp" // Blocks @@ -216,7 +217,7 @@ class CodeHeap : public CHeapObj { int adapter_count() { return _adapter_count; } void set_adapter_count(int count) { _adapter_count = count; } int full_count() { return _full_count; } - void report_full() { _full_count++; } + int report_full() { return Atomic::add(&_full_count, 1); } private: size_t heap_unallocated_capacity() const; diff --git a/src/hotspot/share/memory/operator_new.cpp b/src/hotspot/share/memory/operator_new.cpp deleted file mode 100644 index 357e26f9c88a6c9ba318f3836d7820b81b413b0a..0000000000000000000000000000000000000000 --- a/src/hotspot/share/memory/operator_new.cpp +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Copyright (c) 1997, 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. - * - */ - -#include "precompiled.hpp" -#include "utilities/debug.hpp" - -#include - -//-------------------------------------------------------------------------------------- -// Non-product code - -#ifndef PRODUCT -// The global operator new should never be called since it will usually indicate -// a memory leak. Use CHeapObj as the base class of such objects to make it explicit -// that they're allocated on the C heap. -// Commented out in product version to avoid conflicts with third-party C++ native code. -// -// In C++98/03 the throwing new operators are defined with the following signature: -// -// void* operator new(std::size_tsize) throw(std::bad_alloc); -// void* operator new[](std::size_tsize) throw(std::bad_alloc); -// -// while all the other (non-throwing) new and delete operators are defined with an empty -// throw clause (i.e. "operator delete(void* p) throw()") which means that they do not -// throw any exceptions (see section 18.4 of the C++ standard). -// -// In the new C++11/14 standard, the signature of the throwing new operators was changed -// by completely omitting the throw clause (which effectively means they could throw any -// exception) while all the other new/delete operators where changed to have a 'nothrow' -// clause instead of an empty throw clause. -// -// Unfortunately, the support for exception specifications among C++ compilers is still -// very fragile. While some more strict compilers like AIX xlC or HP aCC reject to -// override the default throwing new operator with a user operator with an empty throw() -// clause, the MS Visual C++ compiler warns for every non-empty throw clause like -// throw(std::bad_alloc) that it will ignore the exception specification. The following -// operator definitions have been checked to correctly work with all currently supported -// compilers and they should be upwards compatible with C++11/14. Therefore -// PLEASE BE CAREFUL if you change the signature of the following operators! - -static void * zero = (void *) 0; - -void* operator new(size_t size) /* throw(std::bad_alloc) */ { - fatal("Should not call global operator new"); - return zero; -} - -void* operator new [](size_t size) /* throw(std::bad_alloc) */ { - fatal("Should not call global operator new[]"); - return zero; -} - -void* operator new(size_t size, const std::nothrow_t& nothrow_constant) throw() { - fatal("Should not call global operator new"); - return 0; -} - -void* operator new [](size_t size, std::nothrow_t& nothrow_constant) throw() { - fatal("Should not call global operator new[]"); - return 0; -} - -void operator delete(void* p) throw() { - fatal("Should not call global delete"); -} - -void operator delete [](void* p) throw() { - fatal("Should not call global delete []"); -} - -void operator delete(void* p, size_t size) throw() { - fatal("Should not call global sized delete"); -} - -void operator delete [](void* p, size_t size) throw() { - fatal("Should not call global sized delete []"); -} - -#endif // Non-product diff --git a/src/hotspot/share/memory/universe.cpp b/src/hotspot/share/memory/universe.cpp index 998ff620f0845012221fa347f520f4a343645ed8..ef244b66912a68c0ab8cd83f53f811536866a8f6 100644 --- a/src/hotspot/share/memory/universe.cpp +++ b/src/hotspot/share/memory/universe.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2022, Oracle and/or its affiliates. All rights reserved. * 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,12 +196,6 @@ void Universe::replace_mirror(BasicType t, oop new_mirror) { Universe::_mirrors[t].replace(new_mirror); } -void Universe::basic_type_classes_do(void f(Klass*)) { - for (int i = T_BOOLEAN; i < T_LONG+1; i++) { - f(_typeArrayKlassObjs[i]); - } -} - void Universe::basic_type_classes_do(KlassClosure *closure) { for (int i = T_BOOLEAN; i < T_LONG+1; i++) { closure->do_klass(_typeArrayKlassObjs[i]); @@ -1254,6 +1248,7 @@ bool Universe::release_fullgc_alot_dummy() { if (_fullgc_alot_dummy_next >= fullgc_alot_dummy_array->length()) { // No more dummies to release, release entire array instead _fullgc_alot_dummy_array.release(Universe::vm_global()); + _fullgc_alot_dummy_array = OopHandle(); // NULL out OopStorage pointer. return false; } diff --git a/src/hotspot/share/memory/universe.hpp b/src/hotspot/share/memory/universe.hpp index 7af2b4b6eaf1ace7a56258742dae52636c67ba4e..6c4cb87494046b048b6b51da62ebd893d3d3e8c9 100644 --- a/src/hotspot/share/memory/universe.hpp +++ b/src/hotspot/share/memory/universe.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -329,9 +329,8 @@ class Universe: AllStatic { // CDS support static void serialize(SerializeClosure* f); - // Apply "f" to all klasses for basic types (classes not present in + // Apply the closure to all klasses for basic types (classes not present in // SystemDictionary). - static void basic_type_classes_do(void f(Klass*)); static void basic_type_classes_do(KlassClosure* closure); static void metaspace_pointers_do(MetaspaceClosure* it); diff --git a/src/hotspot/share/memory/virtualspace.cpp b/src/hotspot/share/memory/virtualspace.cpp index ad918dea29b2638f85edc2f7e17d5bff62dfd25f..b02d723baab81299080224c5b43e77fd22cbc24e 100644 --- a/src/hotspot/share/memory/virtualspace.cpp +++ b/src/hotspot/share/memory/virtualspace.cpp @@ -139,6 +139,19 @@ static bool large_pages_requested() { (!FLAG_IS_DEFAULT(UseLargePages) || !FLAG_IS_DEFAULT(LargePageSizeInBytes)); } +static void log_on_large_pages_failure(char* req_addr, size_t bytes) { + if (large_pages_requested()) { + // Compressed oops logging. + log_debug(gc, heap, coops)("Reserve regular memory without large pages"); + // JVM style warning that we did not succeed in using large pages. + char msg[128]; + jio_snprintf(msg, sizeof(msg), "Failed to reserve and commit memory using large pages. " + "req_addr: " PTR_FORMAT " bytes: " SIZE_FORMAT, + req_addr, bytes); + warning("%s", msg); + } +} + static char* reserve_memory(char* requested_address, const size_t size, const size_t alignment, int fd, bool exec) { char* base; @@ -183,10 +196,6 @@ static char* reserve_memory_special(char* requested_address, const size_t size, "reserve_memory_special() returned an unaligned address, base: " PTR_FORMAT " alignment: " SIZE_FORMAT_HEX, p2i(base), alignment); - } else { - if (large_pages_requested()) { - log_debug(gc, heap, coops)("Reserve regular memory without large pages"); - } } return base; } @@ -235,14 +244,25 @@ void ReservedSpace::reserve(size_t size, // the caller requested large pages. To satisfy this request we use // explicit large pages and these have to be committed up front to ensure // no reservations are lost. + size_t used_page_size = page_size; + char* base = NULL; + + do { + base = reserve_memory_special(requested_address, size, alignment, used_page_size, executable); + if (base != NULL) { + break; + } + used_page_size = os::page_sizes().next_smaller(used_page_size); + } while (used_page_size > (size_t) os::vm_page_size()); - char* base = reserve_memory_special(requested_address, size, alignment, page_size, executable); if (base != NULL) { // Successful reservation using large pages. - initialize_members(base, size, alignment, page_size, true, executable); + initialize_members(base, size, alignment, used_page_size, true, executable); return; } - // Failed to reserve explicit large pages, fall back to normal reservation. + // Failed to reserve explicit large pages, do proper logging. + log_on_large_pages_failure(requested_address, size); + // Now fall back to normal reservation. page_size = os::vm_page_size(); } diff --git a/src/hotspot/share/oops/compiledICHolder.cpp b/src/hotspot/share/oops/compiledICHolder.cpp index a285998a23645c61aa8c601f12635e728122de77..c6ca6be203057d835b00b48f9cc11c92aac35c5a 100644 --- a/src/hotspot/share/oops/compiledICHolder.cpp +++ b/src/hotspot/share/oops/compiledICHolder.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2018, 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 @@ -26,9 +26,10 @@ #include "oops/compiledICHolder.hpp" #include "runtime/atomic.hpp" +#ifdef ASSERT volatile int CompiledICHolder::_live_count; volatile int CompiledICHolder::_live_not_claimed_count; - +#endif CompiledICHolder::CompiledICHolder(Metadata* metadata, Klass* klass, bool is_method) : _holder_metadata(metadata), _holder_klass(klass), _is_metadata_method(is_method) { diff --git a/src/hotspot/share/oops/compiledICHolder.hpp b/src/hotspot/share/oops/compiledICHolder.hpp index b3d0c8715bf840f43017c34eaa48f3ee60271dab..5ddcf07d9cecf2131aa057ae83faf29e6993104a 100644 --- a/src/hotspot/share/oops/compiledICHolder.hpp +++ b/src/hotspot/share/oops/compiledICHolder.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 @@ -44,9 +44,11 @@ class CompiledICHolder : public CHeapObj { friend class VMStructs; private: +#ifdef ASSERT static volatile int _live_count; // allocated static volatile int _live_not_claimed_count; // allocated but not yet in use so not // reachable by iterating over nmethods +#endif Metadata* _holder_metadata; Klass* _holder_klass; // to avoid name conflict with oopDesc::_klass @@ -58,8 +60,10 @@ class CompiledICHolder : public CHeapObj { CompiledICHolder(Metadata* metadata, Klass* klass, bool is_method = true); ~CompiledICHolder() NOT_DEBUG_RETURN; +#ifdef ASSERT static int live_count() { return _live_count; } static int live_not_claimed_count() { return _live_not_claimed_count; } +#endif // accessors Klass* holder_klass() const { return _holder_klass; } diff --git a/src/hotspot/share/oops/instanceKlass.cpp b/src/hotspot/share/oops/instanceKlass.cpp index e635b82f2cebe5c5b7f063fff1869a5fa12866ec..e5dbd1f293e3a809be17d014068b2dfb8f822bbc 100644 --- a/src/hotspot/share/oops/instanceKlass.cpp +++ b/src/hotspot/share/oops/instanceKlass.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,6 +26,7 @@ #include "jvm.h" #include "cds/archiveUtils.hpp" #include "cds/classListWriter.hpp" +#include "cds/heapShared.hpp" #include "cds/metaspaceShared.hpp" #include "classfile/classFileParser.hpp" #include "classfile/classFileStream.hpp" @@ -1503,6 +1504,17 @@ void InstanceKlass::call_class_initializer(TRAPS) { return; } +#if INCLUDE_CDS + // This is needed to ensure the consistency of the archived heap objects. + if (has_archived_enum_objs()) { + assert(is_shared(), "must be"); + bool initialized = HeapShared::initialize_enum_klass(this, CHECK); + if (initialized) { + return; + } + } +#endif + methodHandle h_method(THREAD, class_initializer()); assert(!is_initialized(), "we cannot initialize twice"); LogTarget(Info, class, init) lt; @@ -2062,6 +2074,52 @@ Method* InstanceKlass::lookup_method_in_all_interfaces(Symbol* name, return NULL; } +PrintClassClosure::PrintClassClosure(outputStream* st, bool verbose) + :_st(st), _verbose(verbose) { + ResourceMark rm; + _st->print("%-18s ", "KlassAddr"); + _st->print("%-4s ", "Size"); + _st->print("%-20s ", "State"); + _st->print("%-7s ", "Flags"); + _st->print("%-5s ", "ClassName"); + _st->cr(); +} + +void PrintClassClosure::do_klass(Klass* k) { + ResourceMark rm; + // klass pointer + _st->print(INTPTR_FORMAT " ", p2i(k)); + // klass size + _st->print("%4d ", k->size()); + // initialization state + if (k->is_instance_klass()) { + _st->print("%-20s ",InstanceKlass::cast(k)->init_state_name()); + } else { + _st->print("%-20s ",""); + } + // misc flags(Changes should synced with ClassesDCmd::ClassesDCmd help doc) + char buf[10]; + int i = 0; + if (k->has_finalizer()) buf[i++] = 'F'; + if (k->has_final_method()) buf[i++] = 'f'; + if (k->is_instance_klass()) { + InstanceKlass* ik = InstanceKlass::cast(k); + if (ik->is_rewritten()) buf[i++] = 'W'; + if (ik->is_contended()) buf[i++] = 'C'; + if (ik->has_been_redefined()) buf[i++] = 'R'; + if (ik->is_shared()) buf[i++] = 'S'; + } + buf[i++] = '\0'; + _st->print("%-7s ", buf); + // klass name + _st->print("%-5s ", k->external_name()); + // end + _st->cr(); + if (_verbose) { + k->print_on(_st); + } +} + /* jni_id_for for jfieldIds only */ JNIid* InstanceKlass::jni_id_for(int offset) { MutexLocker ml(JfieldIdCreation_lock); @@ -3381,6 +3439,10 @@ static void print_vtable(vtableEntry* start, int len, outputStream* st) { return print_vtable(reinterpret_cast(start), len, st); } +const char* InstanceKlass::init_state_name() const { + return state_names[_init_state]; +} + void InstanceKlass::print_on(outputStream* st) const { assert(is_klass(), "must be klass"); Klass::print_on(st); @@ -3388,7 +3450,7 @@ void InstanceKlass::print_on(outputStream* st) const { st->print(BULLET"instance size: %d", size_helper()); st->cr(); st->print(BULLET"klass size: %d", size()); st->cr(); st->print(BULLET"access: "); access_flags().print_on(st); st->cr(); - st->print(BULLET"state: "); st->print_cr("%s", state_names[_init_state]); + st->print(BULLET"state: "); st->print_cr("%s", init_state_name()); st->print(BULLET"name: "); name()->print_value_on(st); st->cr(); st->print(BULLET"super: "); Metadata::print_value_on_maybe_null(st, super()); st->cr(); st->print(BULLET"sub: "); diff --git a/src/hotspot/share/oops/instanceKlass.hpp b/src/hotspot/share/oops/instanceKlass.hpp index 11f03cc149bdeff6979c80e357287889a91e408b..9ec3535e0dc3a9448490da93b9bcb8b038ce59f8 100644 --- a/src/hotspot/share/oops/instanceKlass.hpp +++ b/src/hotspot/share/oops/instanceKlass.hpp @@ -547,6 +547,7 @@ public: bool is_in_error_state() const { return _init_state == initialization_error; } bool is_reentrant_initialization(Thread *thread) { return thread == _init_thread; } ClassState init_state() { return (ClassState)_init_state; } + const char* init_state_name() const; bool is_rewritten() const { return (_misc_flags & _misc_rewritten) != 0; } // is this a sealed class @@ -1277,6 +1278,15 @@ inline u2 InstanceKlass::next_method_idnum() { } } +class PrintClassClosure : public KlassClosure { +private: + outputStream* _st; + bool _verbose; +public: + PrintClassClosure(outputStream* st, bool verbose); + + void do_klass(Klass* k); +}; /* JNIid class for jfieldIDs only */ class JNIid: public CHeapObj { diff --git a/src/hotspot/share/oops/klass.hpp b/src/hotspot/share/oops/klass.hpp index 24f7df02cc898e522250d38a187787933a2c4c04..9871036d5764b6364ec9d743b8ac891f446d5c29 100644 --- a/src/hotspot/share/oops/klass.hpp +++ b/src/hotspot/share/oops/klass.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -173,10 +173,11 @@ private: // Flags of the current shared class. u2 _shared_class_flags; enum { - _archived_lambda_proxy_is_available = 2, - _has_value_based_class_annotation = 4, - _verified_at_dump_time = 8, - _regenerated = 16 + _archived_lambda_proxy_is_available = 1 << 1, + _has_value_based_class_annotation = 1 << 2, + _verified_at_dump_time = 1 << 3, + _has_archived_enum_objs = 1 << 4, + _regenerated = 1 << 5 }; #endif @@ -340,6 +341,14 @@ protected: NOT_CDS(return false;) } + void set_has_archived_enum_objs() { + CDS_ONLY(_shared_class_flags |= _has_archived_enum_objs;) + } + bool has_archived_enum_objs() const { + CDS_ONLY(return (_shared_class_flags & _has_archived_enum_objs) != 0;) + NOT_CDS(return false;) + } + void set_regenerated() { CDS_ONLY(_shared_class_flags |= _regenerated;) } diff --git a/src/hotspot/share/oops/method.cpp b/src/hotspot/share/oops/method.cpp index 04ccc8af829725dc5af8b7750a90d3fe0abdda90..490ca305046758c4fccf4eab53751dec5e6dec61 100644 --- a/src/hotspot/share/oops/method.cpp +++ b/src/hotspot/share/oops/method.cpp @@ -83,6 +83,7 @@ Method* Method::allocate(ClassLoaderData* loader_data, AccessFlags access_flags, InlineTableSizes* sizes, ConstMethod::MethodType method_type, + Symbol* name, TRAPS) { assert(!access_flags.is_native() || byte_code_size == 0, "native methods should not contain byte codes"); @@ -92,10 +93,10 @@ Method* Method::allocate(ClassLoaderData* loader_data, method_type, CHECK_NULL); int size = Method::size(access_flags.is_native()); - return new (loader_data, size, MetaspaceObj::MethodType, THREAD) Method(cm, access_flags); + return new (loader_data, size, MetaspaceObj::MethodType, THREAD) Method(cm, access_flags, name); } -Method::Method(ConstMethod* xconst, AccessFlags access_flags) { +Method::Method(ConstMethod* xconst, AccessFlags access_flags, Symbol* name) { NoSafepointVerifier no_safepoint; set_constMethod(xconst); set_access_flags(access_flags); @@ -119,6 +120,8 @@ Method::Method(ConstMethod* xconst, AccessFlags access_flags) { } NOT_PRODUCT(set_compiled_invocation_count(0);) + // Name is very useful for debugging. + NOT_PRODUCT(_name = name;) } // Release Method*. The nmethod will be gone when we get here because @@ -393,6 +396,7 @@ void Method::metaspace_pointers_do(MetaspaceClosure* it) { } it->push(&_method_data); it->push(&_method_counters); + NOT_PRODUCT(it->push(&_name);) } // Attempt to return method to original state. Clear any pointers @@ -1446,7 +1450,9 @@ methodHandle Method::make_method_handle_intrinsic(vmIntrinsics::ID iid, InlineTableSizes sizes; Method* m_oop = Method::allocate(loader_data, 0, accessFlags_from(flags_bits), &sizes, - ConstMethod::NORMAL, CHECK_(empty)); + ConstMethod::NORMAL, + name, + CHECK_(empty)); m = methodHandle(THREAD, m_oop); } m->set_constants(cp()); @@ -1526,6 +1532,7 @@ methodHandle Method::clone_with_new_data(const methodHandle& m, u_char* new_code flags, &sizes, m->method_type(), + m->name(), CHECK_(methodHandle())); methodHandle newm (THREAD, newm_oop); diff --git a/src/hotspot/share/oops/method.hpp b/src/hotspot/share/oops/method.hpp index 9f31bbbea65712c2cd9e39d6b8064b3f35eaa216..15d53a0cf4b32935dbce39715bb037116661cab4 100644 --- a/src/hotspot/share/oops/method.hpp +++ b/src/hotspot/share/oops/method.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -69,6 +69,7 @@ class InterpreterOopMap; class Method : public Metadata { friend class VMStructs; friend class JVMCIVMStructs; + friend class MethodTest; private: // If you add a new field that points to any metaspace object, you // must add this field to Method::metaspace_pointers_do(). @@ -98,6 +99,8 @@ class Method : public Metadata { #ifndef PRODUCT int64_t _compiled_invocation_count; + + Symbol* _name; #endif // Entry point for calling both from and to the interpreter. address _i2i_entry; // All-args-on-stack calling convention @@ -113,7 +116,7 @@ class Method : public Metadata { volatile address _from_interpreted_entry; // Cache of _code ? _adapter->i2c_entry() : _i2i_entry // Constructor - Method(ConstMethod* xconst, AccessFlags access_flags); + Method(ConstMethod* xconst, AccessFlags access_flags, Symbol* name); public: static Method* allocate(ClassLoaderData* loader_data, @@ -121,6 +124,7 @@ class Method : public Metadata { AccessFlags access_flags, InlineTableSizes* sizes, ConstMethod::MethodType method_type, + Symbol* name, TRAPS); // CDS and vtbl checking can create an empty Method to get vtbl pointer. diff --git a/src/hotspot/share/opto/arraycopynode.cpp b/src/hotspot/share/opto/arraycopynode.cpp index 11560f6419baf37122350324550af6c79ffcd01f..b0f30703f91f0eb1e3e4ad184c5f6783e2d1fc7d 100644 --- a/src/hotspot/share/opto/arraycopynode.cpp +++ b/src/hotspot/share/opto/arraycopynode.cpp @@ -189,9 +189,8 @@ Node* ArrayCopyNode::try_clone_instance(PhaseGVN *phase, bool can_reshape, int c } MergeMemNode* mem = phase->transform(MergeMemNode::make(in_mem))->as_MergeMem(); - PhaseIterGVN* igvn = phase->is_IterGVN(); - if (igvn != NULL) { - igvn->_worklist.push(mem); + if (can_reshape) { + phase->is_IterGVN()->_worklist.push(mem); } if (!inst_src->klass_is_exact()) { @@ -294,9 +293,17 @@ bool ArrayCopyNode::prepare_array_copy(PhaseGVN *phase, bool can_reshape, uint header = arrayOopDesc::base_offset_in_bytes(dest_elem); src_offset = Compile::conv_I2X_index(phase, src_offset, ary_src->size()); + if (src_offset->is_top()) { + // Offset is out of bounds (the ArrayCopyNode will be removed) + return false; + } dest_offset = Compile::conv_I2X_index(phase, dest_offset, ary_dest->size()); - if (src_offset->is_top() || dest_offset->is_top()) { + if (dest_offset->is_top()) { // Offset is out of bounds (the ArrayCopyNode will be removed) + if (can_reshape) { + // record src_offset, so it can be deleted later (if it is dead) + phase->is_IterGVN()->_worklist.push(src_offset); + } return false; } @@ -316,9 +323,6 @@ bool ArrayCopyNode::prepare_array_copy(PhaseGVN *phase, bool can_reshape, disjoint_bases = true; - adr_src = phase->transform(new AddPNode(base_src, base_src, src_offset)); - adr_dest = phase->transform(new AddPNode(base_dest, base_dest, dest_offset)); - BasicType elem = ary_src->klass()->as_array_klass()->element_type()->basic_type(); if (is_reference_type(elem)) { elem = T_OBJECT; @@ -329,6 +333,9 @@ bool ArrayCopyNode::prepare_array_copy(PhaseGVN *phase, bool can_reshape, return false; } + adr_src = phase->transform(new AddPNode(base_src, base_src, src_offset)); + adr_dest = phase->transform(new AddPNode(base_dest, base_dest, dest_offset)); + // The address is offseted to an aligned address where a raw copy would start. // If the clone copy is decomposed into load-stores - the address is adjusted to // point at where the array starts. @@ -566,6 +573,8 @@ Node *ArrayCopyNode::Ideal(PhaseGVN *phase, bool can_reshape) { if (!prepare_array_copy(phase, can_reshape, adr_src, base_src, adr_dest, base_dest, copy_type, value_type, disjoint_bases)) { + assert(adr_src == NULL, "no node can be left behind"); + assert(adr_dest == NULL, "no node can be left behind"); return NULL; } @@ -629,6 +638,10 @@ Node *ArrayCopyNode::Ideal(PhaseGVN *phase, bool can_reshape) { } if (!finish_transform(phase, can_reshape, ctl, mem)) { + if (can_reshape) { + // put in worklist, so that if it happens to be dead it is removed + phase->is_IterGVN()->_worklist.push(mem); + } return NULL; } diff --git a/src/hotspot/share/opto/c2compiler.cpp b/src/hotspot/share/opto/c2compiler.cpp index af2b8e5456c6728083149f1b4893425437b0d0f5..94e7fb4f4a0d6a456b444634c33edc59755fa152 100644 --- a/src/hotspot/share/opto/c2compiler.cpp +++ b/src/hotspot/share/opto/c2compiler.cpp @@ -234,8 +234,8 @@ bool C2Compiler::is_intrinsic_supported(const methodHandle& method, bool is_virt case vmIntrinsics::_encodeByteISOArray: if (!Matcher::match_rule_supported(Op_EncodeISOArray)) return false; break; - case vmIntrinsics::_hasNegatives: - if (!Matcher::match_rule_supported(Op_HasNegatives)) return false; + case vmIntrinsics::_countPositives: + if (!Matcher::match_rule_supported(Op_CountPositives)) return false; break; case vmIntrinsics::_bitCount_i: if (!Matcher::match_rule_supported(Op_PopCountI)) return false; diff --git a/src/hotspot/share/opto/callGenerator.cpp b/src/hotspot/share/opto/callGenerator.cpp index 9931f2562986a41668f7a5c1446590953663a5d7..7819965f57d364b1673d6e40968be5c687c7d4df 100644 --- a/src/hotspot/share/opto/callGenerator.cpp +++ b/src/hotspot/share/opto/callGenerator.cpp @@ -526,12 +526,20 @@ bool LateInlineVirtualCallGenerator::do_late_inline_check(Compile* C, JVMState* Node* receiver = jvms->map()->argument(jvms, 0); const Type* recv_type = C->initial_gvn()->type(receiver); if (recv_type->maybe_null()) { + if (C->print_inlining() || C->print_intrinsics()) { + C->print_inlining(method(), jvms->depth()-1, call_node()->jvms()->bci(), + "late call devirtualization failed (receiver may be null)"); + } return false; } // Even if inlining is not allowed, a virtual call can be strength-reduced to a direct call. bool allow_inline = C->inlining_incrementally(); if (!allow_inline && _callee->holder()->is_interface()) { // Don't convert the interface call to a direct call guarded by an interface subtype check. + if (C->print_inlining() || C->print_intrinsics()) { + C->print_inlining(method(), jvms->depth()-1, call_node()->jvms()->bci(), + "late call devirtualization failed (interface call)"); + } return false; } CallGenerator* cg = C->call_generator(_callee, diff --git a/src/hotspot/share/opto/castnode.cpp b/src/hotspot/share/opto/castnode.cpp index 44799635db094a7af5840ee04ab8586f7cfdaef5..97c518b8ae519eb65427c06c3702b457e4fc3bab 100644 --- a/src/hotspot/share/opto/castnode.cpp +++ b/src/hotspot/share/opto/castnode.cpp @@ -194,6 +194,40 @@ void ConstraintCastNode::dump_spec(outputStream *st) const { const Type* CastIINode::Value(PhaseGVN* phase) const { const Type *res = ConstraintCastNode::Value(phase); + if (res == Type::TOP) { + return Type::TOP; + } + assert(res->isa_int(), "res must be int"); + + // Similar to ConvI2LNode::Value() for the same reasons + // see if we can remove type assertion after loop opts + // But here we have to pay extra attention: + // Do not narrow the type of range check dependent CastIINodes to + // avoid corruption of the graph if a CastII is replaced by TOP but + // the corresponding range check is not removed. + if (!_range_check_dependency && phase->C->post_loop_opts_phase()) { + const TypeInt* this_type = res->is_int(); + const TypeInt* in_type = phase->type(in(1))->isa_int(); + if (in_type != NULL && + (in_type->_lo != this_type->_lo || + in_type->_hi != this_type->_hi)) { + jint lo1 = this_type->_lo; + jint hi1 = this_type->_hi; + int w1 = this_type->_widen; + if (lo1 >= 0) { + // Keep a range assertion of >=0. + lo1 = 0; hi1 = max_jint; + } else if (hi1 < 0) { + // Keep a range assertion of <0. + lo1 = min_jint; hi1 = -1; + } else { + lo1 = min_jint; hi1 = max_jint; + } + res = TypeInt::make(MAX2(in_type->_lo, lo1), + MIN2(in_type->_hi, hi1), + MAX2((int)in_type->_widen, w1)); + } + } // Try to improve the type of the CastII if we recognize a CmpI/If // pattern. @@ -248,7 +282,6 @@ const Type* CastIINode::Value(PhaseGVN* phase) const { t = TypeInt::make(lo_int, hi_int, Type::WidenMax); res = res->filter_speculative(t); - return res; } } @@ -274,8 +307,11 @@ Node *CastIINode::Ideal(PhaseGVN *phase, bool can_reshape) { if (progress != NULL) { return progress; } - - PhaseIterGVN *igvn = phase->is_IterGVN(); + if (can_reshape && !_range_check_dependency && !phase->C->post_loop_opts_phase()) { + // makes sure we run ::Value to potentially remove type assertion after loop opts + phase->C->record_for_post_loop_opts_igvn(this); + } + PhaseIterGVN* igvn = phase->is_IterGVN(); const TypeInt* this_type = this->type()->is_int(); Node* z = in(1); const TypeInteger* rx = NULL; @@ -300,43 +336,6 @@ Node *CastIINode::Ideal(PhaseGVN *phase, bool can_reshape) { default: ShouldNotReachHere(); } } - - // Similar to ConvI2LNode::Ideal() for the same reasons - // Do not narrow the type of range check dependent CastIINodes to - // avoid corruption of the graph if a CastII is replaced by TOP but - // the corresponding range check is not removed. - if (can_reshape && !_range_check_dependency) { - if (phase->C->post_loop_opts_phase()) { - const TypeInt* this_type = this->type()->is_int(); - const TypeInt* in_type = phase->type(in(1))->isa_int(); - if (in_type != NULL && this_type != NULL && - (in_type->_lo != this_type->_lo || - in_type->_hi != this_type->_hi)) { - jint lo1 = this_type->_lo; - jint hi1 = this_type->_hi; - int w1 = this_type->_widen; - - if (lo1 >= 0) { - // Keep a range assertion of >=0. - lo1 = 0; hi1 = max_jint; - } else if (hi1 < 0) { - // Keep a range assertion of <0. - lo1 = min_jint; hi1 = -1; - } else { - lo1 = min_jint; hi1 = max_jint; - } - const TypeInt* wtype = TypeInt::make(MAX2(in_type->_lo, lo1), - MIN2(in_type->_hi, hi1), - MAX2((int)in_type->_widen, w1)); - if (wtype != type()) { - set_type(wtype); - return this; - } - } - } else { - phase->C->record_for_post_loop_opts_igvn(this); - } - } return NULL; } diff --git a/src/hotspot/share/opto/classes.hpp b/src/hotspot/share/opto/classes.hpp index 4abb3fef3b47bc8ba0ad51728a998f567012027e..35dd640b4eea7681e2e38c2e5968b5c52a0de28a 100644 --- a/src/hotspot/share/opto/classes.hpp +++ b/src/hotspot/share/opto/classes.hpp @@ -174,7 +174,7 @@ macro(FmaD) macro(FmaF) macro(Goto) macro(Halt) -macro(HasNegatives) +macro(CountPositives) macro(If) macro(RangeCheck) macro(IfFalse) diff --git a/src/hotspot/share/opto/compile.cpp b/src/hotspot/share/opto/compile.cpp index 8a341a00d183e40515200eeec41e188a52134cb0..c80eabca43b6ef4a6e1b2394aa41edf2c0e59233 100644 --- a/src/hotspot/share/opto/compile.cpp +++ b/src/hotspot/share/opto/compile.cpp @@ -4833,7 +4833,7 @@ void Compile::print_method(CompilerPhaseType cpt, int level, Node* n) { #ifndef PRODUCT ResourceMark rm; stringStream ss; - ss.print_raw(CompilerPhaseTypeHelper::to_name(cpt)); + ss.print_raw(CompilerPhaseTypeHelper::to_description(cpt)); if (n != nullptr) { ss.print(": %d %s ", n->_idx, NodeClassNames[n->Opcode()]); } diff --git a/src/hotspot/share/opto/convertnode.cpp b/src/hotspot/share/opto/convertnode.cpp index 501cb08c45209b2dbb2a631af263b7793e109296..27cef49e5b6790005f5152b9bbe95f6bd85dd702 100644 --- a/src/hotspot/share/opto/convertnode.cpp +++ b/src/hotspot/share/opto/convertnode.cpp @@ -252,12 +252,47 @@ Node* ConvI2FNode::Identity(PhaseGVN* phase) { //------------------------------Value------------------------------------------ const Type* ConvI2LNode::Value(PhaseGVN* phase) const { const Type *t = phase->type( in(1) ); - if( t == Type::TOP ) return Type::TOP; + if (t == Type::TOP) { + return Type::TOP; + } const TypeInt *ti = t->is_int(); const Type* tl = TypeLong::make(ti->_lo, ti->_hi, ti->_widen); // Join my declared type against my incoming type. tl = tl->filter(_type); - return tl; + if (!tl->isa_long()) { + return tl; + } + const TypeLong* this_type = tl->is_long(); + // Do NOT remove this node's type assertion until no more loop ops can happen. + if (phase->C->post_loop_opts_phase()) { + const TypeInt* in_type = phase->type(in(1))->isa_int(); + if (in_type != NULL && + (in_type->_lo != this_type->_lo || + in_type->_hi != this_type->_hi)) { + // Although this WORSENS the type, it increases GVN opportunities, + // because I2L nodes with the same input will common up, regardless + // of slightly differing type assertions. Such slight differences + // arise routinely as a result of loop unrolling, so this is a + // post-unrolling graph cleanup. Choose a type which depends only + // on my input. (Exception: Keep a range assertion of >=0 or <0.) + jlong lo1 = this_type->_lo; + jlong hi1 = this_type->_hi; + int w1 = this_type->_widen; + if (lo1 >= 0) { + // Keep a range assertion of >=0. + lo1 = 0; hi1 = max_jint; + } else if (hi1 < 0) { + // Keep a range assertion of <0. + lo1 = min_jint; hi1 = -1; + } else { + lo1 = min_jint; hi1 = max_jint; + } + return TypeLong::make(MAX2((jlong)in_type->_lo, lo1), + MIN2((jlong)in_type->_hi, hi1), + MAX2((int)in_type->_widen, w1)); + } + } + return this_type; } static inline bool long_ranges_overlap(jlong lo1, jlong hi1, @@ -359,52 +394,10 @@ bool Compile::push_thru_add(PhaseGVN* phase, Node* z, const TypeInteger* tz, con //------------------------------Ideal------------------------------------------ Node *ConvI2LNode::Ideal(PhaseGVN *phase, bool can_reshape) { - PhaseIterGVN *igvn = phase->is_IterGVN(); const TypeLong* this_type = this->type()->is_long(); - Node* this_changed = NULL; - - if (igvn != NULL) { - // Do NOT remove this node's type assertion until no more loop ops can happen. - if (phase->C->post_loop_opts_phase()) { - const TypeInt* in_type = phase->type(in(1))->isa_int(); - if (in_type != NULL && this_type != NULL && - (in_type->_lo != this_type->_lo || - in_type->_hi != this_type->_hi)) { - // Although this WORSENS the type, it increases GVN opportunities, - // because I2L nodes with the same input will common up, regardless - // of slightly differing type assertions. Such slight differences - // arise routinely as a result of loop unrolling, so this is a - // post-unrolling graph cleanup. Choose a type which depends only - // on my input. (Exception: Keep a range assertion of >=0 or <0.) - jlong lo1 = this_type->_lo; - jlong hi1 = this_type->_hi; - int w1 = this_type->_widen; - if (lo1 != (jint)lo1 || - hi1 != (jint)hi1 || - lo1 > hi1) { - // Overflow leads to wraparound, wraparound leads to range saturation. - lo1 = min_jint; hi1 = max_jint; - } else if (lo1 >= 0) { - // Keep a range assertion of >=0. - lo1 = 0; hi1 = max_jint; - } else if (hi1 < 0) { - // Keep a range assertion of <0. - lo1 = min_jint; hi1 = -1; - } else { - lo1 = min_jint; hi1 = max_jint; - } - const TypeLong* wtype = TypeLong::make(MAX2((jlong)in_type->_lo, lo1), - MIN2((jlong)in_type->_hi, hi1), - MAX2((int)in_type->_widen, w1)); - if (wtype != type()) { - set_type(wtype); - // Note: this_type still has old type value, for the logic below. - this_changed = this; - } - } - } else { - phase->C->record_for_post_loop_opts_igvn(this); - } + if (can_reshape && !phase->C->post_loop_opts_phase()) { + // makes sure we run ::Value to potentially remove type assertion after loop opts + phase->C->record_for_post_loop_opts_igvn(this); } #ifdef _LP64 // Convert ConvI2L(AddI(x, y)) to AddL(ConvI2L(x), ConvI2L(y)) @@ -428,7 +421,7 @@ Node *ConvI2LNode::Ideal(PhaseGVN *phase, bool can_reshape) { // possible before the I2L conversion, because 32-bit math is cheaper. // There's no common reason to "leak" a constant offset through the I2L. // Addressing arithmetic will not absorb it as part of a 64-bit AddL. - + PhaseIterGVN* igvn = phase->is_IterGVN(); Node* z = in(1); const TypeInteger* rx = NULL; const TypeInteger* ry = NULL; @@ -437,7 +430,7 @@ Node *ConvI2LNode::Ideal(PhaseGVN *phase, bool can_reshape) { // Postpone this optimization to iterative GVN, where we can handle deep // AddI chains without an exponential number of recursive Ideal() calls. phase->record_for_igvn(this); - return this_changed; + return NULL; } int op = z->Opcode(); Node* x = z->in(1); @@ -453,7 +446,7 @@ Node *ConvI2LNode::Ideal(PhaseGVN *phase, bool can_reshape) { } #endif //_LP64 - return this_changed; + return NULL; } //============================================================================= diff --git a/src/hotspot/share/opto/escape.cpp b/src/hotspot/share/opto/escape.cpp index c88e6f39993d50133a07a39cc3a6ef022fa2896d..3e02b18f50f35e4c66274172259955e1aa41118b 100644 --- a/src/hotspot/share/opto/escape.cpp +++ b/src/hotspot/share/opto/escape.cpp @@ -217,6 +217,20 @@ bool ConnectionGraph::compute_escape() { sfn_worklist.append(n->as_SafePoint()); } } + +#ifndef PRODUCT + if (_compile->directive()->TraceEscapeAnalysisOption) { + tty->print("+++++ Initial worklist for "); + _compile->method()->print_name(); + tty->print_cr(" (ea_inv=%d)", _invocation); + for (int i = 0; i < ptnodes_worklist.length(); i++) { + PointsToNode* ptn = ptnodes_worklist.at(i); + ptn->dump(); + } + tty->print_cr("+++++ Calculating escape states and scalar replaceability"); + } +#endif + if (non_escaped_allocs_worklist.length() == 0) { _collecting = false; return false; // Nothing to do. @@ -621,7 +635,7 @@ void ConnectionGraph::add_node_to_connection_graph(Node *n, Unique_Node_List *de break; } case Op_AryEq: - case Op_HasNegatives: + case Op_CountPositives: case Op_StrComp: case Op_StrEquals: case Op_StrIndexOf: @@ -759,7 +773,7 @@ void ConnectionGraph::add_final_edges(Node *n) { break; } case Op_AryEq: - case Op_HasNegatives: + case Op_CountPositives: case Op_StrComp: case Op_StrEquals: case Op_StrIndexOf: @@ -865,7 +879,7 @@ bool ConnectionGraph::add_final_edges_unsafe_access(Node* n, uint opcode) { Node* val = n->in(MemNode::ValueIn); PointsToNode* ptn = ptnode_adr(val->_idx); assert(ptn != NULL, "node should be registered"); - set_escape_state(ptn, PointsToNode::GlobalEscape); + set_escape_state(ptn, PointsToNode::GlobalEscape NOT_PRODUCT(COMMA "stored at raw address")); // Add edge to object for unsafe access with offset. PointsToNode* adr_ptn = ptnode_adr(adr->_idx); assert(adr_ptn != NULL, "node should be registered"); @@ -892,14 +906,20 @@ void ConnectionGraph::add_call_node(CallNode* call) { ciKlass* cik = kt->klass(); PointsToNode::EscapeState es = PointsToNode::NoEscape; bool scalar_replaceable = true; + NOT_PRODUCT(const char* nsr_reason = ""); if (call->is_AllocateArray()) { if (!cik->is_array_klass()) { // StressReflectiveCode es = PointsToNode::GlobalEscape; } else { int length = call->in(AllocateNode::ALength)->find_int_con(-1); - if (length < 0 || length > EliminateAllocationArraySizeLimit) { - // Not scalar replaceable if the length is not constant or too big. + if (length < 0) { + // Not scalar replaceable if the length is not constant. scalar_replaceable = false; + NOT_PRODUCT(nsr_reason = "has a non-constant length"); + } else if (length > EliminateAllocationArraySizeLimit) { + // Not scalar replaceable if the length is too big. + scalar_replaceable = false; + NOT_PRODUCT(nsr_reason = "has a length that is too big"); } } } else { // Allocate instance @@ -914,13 +934,14 @@ void ConnectionGraph::add_call_node(CallNode* call) { if (nfields > EliminateAllocationFieldsLimit) { // Not scalar replaceable if there are too many fields. scalar_replaceable = false; + NOT_PRODUCT(nsr_reason = "has too many fields"); } } } add_java_object(call, es); PointsToNode* ptn = ptnode_adr(call_idx); if (!scalar_replaceable && ptn->scalar_replaceable()) { - ptn->set_scalar_replaceable(false); + set_not_scalar_replaceable(ptn NOT_PRODUCT(COMMA nsr_reason)); } } else if (call->is_CallStaticJava()) { // Call nodes could be different types: @@ -951,7 +972,7 @@ void ConnectionGraph::add_call_node(CallNode* call) { assert(strncmp(name, "_multianewarray", 15) == 0, "TODO: add failed case check"); // Returns a newly allocated non-escaped object. add_java_object(call, PointsToNode::NoEscape); - ptnode_adr(call_idx)->set_scalar_replaceable(false); + set_not_scalar_replaceable(ptnode_adr(call_idx) NOT_PRODUCT(COMMA "is result of multinewarray")); } else if (meth->is_boxing_method()) { // Returns boxing object PointsToNode::EscapeState es; @@ -973,7 +994,7 @@ void ConnectionGraph::add_call_node(CallNode* call) { // Mark it as NoEscape so that objects referenced by // it's fields will be marked as NoEscape at least. add_java_object(call, PointsToNode::NoEscape); - ptnode_adr(call_idx)->set_scalar_replaceable(false); + set_not_scalar_replaceable(ptnode_adr(call_idx) NOT_PRODUCT(COMMA "is result of call")); } else { // Determine whether any arguments are returned. const TypeTuple* d = call->tf()->domain(); @@ -1128,7 +1149,7 @@ void ConnectionGraph::process_call_arguments(CallNode *call) { es = PointsToNode::NoEscape; } } - set_escape_state(arg_ptn, es); + set_escape_state(arg_ptn, es NOT_PRODUCT(COMMA trace_arg_escape_message(call))); if (arg_is_arraycopy_dest) { Node* src = call->in(TypeFunc::Parms); if (src->is_AddP()) { @@ -1183,12 +1204,12 @@ void ConnectionGraph::process_call_arguments(CallNode *call) { arg_ptn->escape_state() < PointsToNode::GlobalEscape) { if (!call_analyzer->is_arg_stack(k)) { // The argument global escapes - set_escape_state(arg_ptn, PointsToNode::GlobalEscape); + set_escape_state(arg_ptn, PointsToNode::GlobalEscape NOT_PRODUCT(COMMA trace_arg_escape_message(call))); } else { - set_escape_state(arg_ptn, PointsToNode::ArgEscape); + set_escape_state(arg_ptn, PointsToNode::ArgEscape NOT_PRODUCT(COMMA trace_arg_escape_message(call))); if (!call_analyzer->is_arg_local(k)) { // The argument itself doesn't escape, but any fields might - set_fields_escape_state(arg_ptn, PointsToNode::GlobalEscape); + set_fields_escape_state(arg_ptn, PointsToNode::GlobalEscape NOT_PRODUCT(COMMA trace_arg_escape_message(call))); } } } @@ -1217,7 +1238,7 @@ void ConnectionGraph::process_call_arguments(CallNode *call) { arg = get_addp_base(arg); } assert(ptnode_adr(arg->_idx) != NULL, "should be defined already"); - set_escape_state(ptnode_adr(arg->_idx), PointsToNode::GlobalEscape); + set_escape_state(ptnode_adr(arg->_idx), PointsToNode::GlobalEscape NOT_PRODUCT(COMMA trace_arg_escape_message(call))); } } } @@ -1401,30 +1422,30 @@ bool ConnectionGraph::find_non_escaped_objects(GrowableArray& ptn assert(ptn->arraycopy_dst(), "sanity"); // Propagate only fields escape state through arraycopy edge. if (e->fields_escape_state() < field_es) { - set_fields_escape_state(e, field_es); + set_fields_escape_state(e, field_es NOT_PRODUCT(COMMA trace_propagate_message(ptn))); escape_worklist.push(e); } } else if (es >= field_es) { // fields_escape_state is also set to 'es' if it is less than 'es'. if (e->escape_state() < es) { - set_escape_state(e, es); + set_escape_state(e, es NOT_PRODUCT(COMMA trace_propagate_message(ptn))); escape_worklist.push(e); } } else { // Propagate field escape state. bool es_changed = false; if (e->fields_escape_state() < field_es) { - set_fields_escape_state(e, field_es); + set_fields_escape_state(e, field_es NOT_PRODUCT(COMMA trace_propagate_message(ptn))); es_changed = true; } if ((e->escape_state() < field_es) && e->is_Field() && ptn->is_JavaObject() && e->as_Field()->is_oop()) { // Change escape state of referenced fields. - set_escape_state(e, field_es); + set_escape_state(e, field_es NOT_PRODUCT(COMMA trace_propagate_message(ptn))); es_changed = true; } else if (e->escape_state() < es) { - set_escape_state(e, es); + set_escape_state(e, es NOT_PRODUCT(COMMA trace_propagate_message(ptn))); es_changed = true; } if (es_changed) { @@ -1790,7 +1811,7 @@ void ConnectionGraph::adjust_scalar_replaceable_state(JavaObjectNode* jobj) { // 1. An object is not scalar replaceable if the field into which it is // stored has unknown offset (stored into unknown element of an array). if (field->offset() == Type::OffsetBot) { - jobj->set_scalar_replaceable(false); + set_not_scalar_replaceable(jobj NOT_PRODUCT(COMMA "is stored at unknown offset")); return; } // 2. An object is not scalar replaceable if the field into which it is @@ -1799,7 +1820,7 @@ void ConnectionGraph::adjust_scalar_replaceable_state(JavaObjectNode* jobj) { for (BaseIterator i(field); i.has_next(); i.next()) { PointsToNode* base = i.get(); if (base == null_obj) { - jobj->set_scalar_replaceable(false); + set_not_scalar_replaceable(jobj NOT_PRODUCT(COMMA "is stored into field with potentially null base")); return; } } @@ -1811,8 +1832,8 @@ void ConnectionGraph::adjust_scalar_replaceable_state(JavaObjectNode* jobj) { PointsToNode* ptn = j.get(); if (ptn->is_JavaObject() && ptn != jobj) { // Mark all objects. - jobj->set_scalar_replaceable(false); - ptn->set_scalar_replaceable(false); + set_not_scalar_replaceable(jobj NOT_PRODUCT(COMMA trace_merged_message(ptn))); + set_not_scalar_replaceable(ptn NOT_PRODUCT(COMMA trace_merged_message(jobj))); } } if (!jobj->scalar_replaceable()) { @@ -1832,7 +1853,7 @@ void ConnectionGraph::adjust_scalar_replaceable_state(JavaObjectNode* jobj) { // 4. An object is not scalar replaceable if it has a field with unknown // offset (array's element is accessed in loop). if (offset == Type::OffsetBot) { - jobj->set_scalar_replaceable(false); + set_not_scalar_replaceable(jobj NOT_PRODUCT(COMMA "has field with unknown offset")); return; } // 5. Currently an object is not scalar replaceable if a LoadStore node @@ -1847,14 +1868,14 @@ void ConnectionGraph::adjust_scalar_replaceable_state(JavaObjectNode* jobj) { n->in(AddPNode::Address)->Opcode() == Op_CheckCastPP) { assert(n->in(AddPNode::Address)->bottom_type()->isa_rawptr(), "raw address so raw cast expected"); assert(_igvn->type(n->in(AddPNode::Address)->in(1))->isa_oopptr(), "cast pattern at unsafe access expected"); - jobj->set_scalar_replaceable(false); + set_not_scalar_replaceable(jobj NOT_PRODUCT(COMMA "is used as base of mixed unsafe access")); return; } for (DUIterator_Fast imax, i = n->fast_outs(imax); i < imax; i++) { Node* u = n->fast_out(i); if (u->is_LoadStore() || (u->is_Mem() && u->as_Mem()->is_mismatched_access())) { - jobj->set_scalar_replaceable(false); + set_not_scalar_replaceable(jobj NOT_PRODUCT(COMMA "is used in LoadStore or mismatched access")); return; } } @@ -1883,8 +1904,8 @@ void ConnectionGraph::adjust_scalar_replaceable_state(JavaObjectNode* jobj) { // this field's base by now. if (base->is_JavaObject() && base != jobj) { // Mark all bases. - jobj->set_scalar_replaceable(false); - base->set_scalar_replaceable(false); + set_not_scalar_replaceable(jobj NOT_PRODUCT(COMMA "may point to more than one object")); + set_not_scalar_replaceable(base NOT_PRODUCT(COMMA "may point to more than one object")); } } } @@ -3149,7 +3170,7 @@ void ConnectionGraph::split_unique_types(GrowableArray &alloc_worklist, // so it could be eliminated. alloc->as_Allocate()->_is_scalar_replaceable = true; } - set_escape_state(ptnode_adr(n->_idx), es); // CheckCastPP escape state + set_escape_state(ptnode_adr(n->_idx), es NOT_PRODUCT(COMMA trace_propagate_message(ptn))); // CheckCastPP escape state // in order for an object to be scalar-replaceable, it must be: // - a direct allocation (not a call returning an object) // - non-escaping @@ -3323,7 +3344,8 @@ void ConnectionGraph::split_unique_types(GrowableArray &alloc_worklist, memnode_worklist.append_if_missing(use); } else if (!(op == Op_CmpP || op == Op_Conv2B || op == Op_CastP2X || op == Op_StoreCM || - op == Op_FastLock || op == Op_AryEq || op == Op_StrComp || op == Op_HasNegatives || + op == Op_FastLock || op == Op_AryEq || op == Op_StrComp || + op == Op_CountPositives || op == Op_StrCompressedCopy || op == Op_StrInflatedCopy || op == Op_StrEquals || op == Op_StrIndexOf || op == Op_StrIndexOfChar || op == Op_SubTypeCheck || @@ -3454,7 +3476,7 @@ void ConnectionGraph::split_unique_types(GrowableArray &alloc_worklist, // They overwrite memory edge corresponding to destination array, memnode_worklist.append_if_missing(use); } else if (!(BarrierSet::barrier_set()->barrier_set_c2()->is_gc_barrier_node(use) || - op == Op_AryEq || op == Op_StrComp || op == Op_HasNegatives || + op == Op_AryEq || op == Op_StrComp || op == Op_CountPositives || op == Op_StrCompressedCopy || op == Op_StrInflatedCopy || op == Op_StrEquals || op == Op_StrIndexOf || op == Op_StrIndexOfChar)) { n->dump(); @@ -3624,38 +3646,42 @@ static const char *esc_names[] = { "GlobalEscape" }; -void PointsToNode::dump(bool print_state) const { +void PointsToNode::dump_header(bool print_state, outputStream* out) const { NodeType nt = node_type(); - tty->print("%s ", node_type_names[(int) nt]); + out->print("%s(%d) ", node_type_names[(int) nt], _pidx); if (print_state) { EscapeState es = escape_state(); EscapeState fields_es = fields_escape_state(); - tty->print("%s(%s) ", esc_names[(int)es], esc_names[(int)fields_es]); + out->print("%s(%s) ", esc_names[(int)es], esc_names[(int)fields_es]); if (nt == PointsToNode::JavaObject && !this->scalar_replaceable()) { - tty->print("NSR "); + out->print("NSR "); } } +} + +void PointsToNode::dump(bool print_state, outputStream* out, bool newline) const { + dump_header(print_state, out); if (is_Field()) { FieldNode* f = (FieldNode*)this; if (f->is_oop()) { - tty->print("oop "); + out->print("oop "); } if (f->offset() > 0) { - tty->print("+%d ", f->offset()); + out->print("+%d ", f->offset()); } - tty->print("("); + out->print("("); for (BaseIterator i(f); i.has_next(); i.next()) { PointsToNode* b = i.get(); - tty->print(" %d%s", b->idx(),(b->is_JavaObject() ? "P" : "")); + out->print(" %d%s", b->idx(),(b->is_JavaObject() ? "P" : "")); } - tty->print(" )"); + out->print(" )"); } - tty->print("["); + out->print("["); for (EdgeIterator i(this); i.has_next(); i.next()) { PointsToNode* e = i.get(); - tty->print(" %d%s%s", e->idx(),(e->is_JavaObject() ? "P" : (e->is_Field() ? "F" : "")), e->is_Arraycopy() ? "cp" : ""); + out->print(" %d%s%s", e->idx(),(e->is_JavaObject() ? "P" : (e->is_Field() ? "F" : "")), e->is_Arraycopy() ? "cp" : ""); } - tty->print(" ["); + out->print(" ["); for (UseIterator i(this); i.has_next(); i.next()) { PointsToNode* u = i.get(); bool is_base = false; @@ -3663,13 +3689,13 @@ void PointsToNode::dump(bool print_state) const { is_base = true; u = PointsToNode::get_use_node(u)->as_Field(); } - tty->print(" %d%s%s", u->idx(), is_base ? "b" : "", u->is_Arraycopy() ? "cp" : ""); + out->print(" %d%s%s", u->idx(), is_base ? "b" : "", u->is_Arraycopy() ? "cp" : ""); } - tty->print(" ]] "); + out->print(" ]] "); if (_node == NULL) { - tty->print_cr(""); + out->print("%s", newline ? "\n" : ""); } else { - _node->dump(); + _node->dump(newline ? "\n" : "", false, out); } } @@ -3712,6 +3738,51 @@ void ConnectionGraph::dump(GrowableArray& ptnodes_worklist) { } } } + +void ConnectionGraph::trace_es_update_helper(PointsToNode* ptn, PointsToNode::EscapeState es, bool fields, const char* reason) const { + if (_compile->directive()->TraceEscapeAnalysisOption) { + assert(ptn != nullptr, "should not be null"); + assert(reason != nullptr, "should not be null"); + ptn->dump_header(true); + PointsToNode::EscapeState new_es = fields ? ptn->escape_state() : es; + PointsToNode::EscapeState new_fields_es = fields ? es : ptn->fields_escape_state(); + tty->print_cr("-> %s(%s) %s", esc_names[(int)new_es], esc_names[(int)new_fields_es], reason); + } +} + +const char* ConnectionGraph::trace_propagate_message(PointsToNode* from) const { + if (_compile->directive()->TraceEscapeAnalysisOption) { + stringStream ss; + ss.print("propagated from: "); + from->dump(true, &ss, false); + return ss.as_string(); + } else { + return nullptr; + } +} + +const char* ConnectionGraph::trace_arg_escape_message(CallNode* call) const { + if (_compile->directive()->TraceEscapeAnalysisOption) { + stringStream ss; + ss.print("escapes as arg to:"); + call->dump("", false, &ss); + return ss.as_string(); + } else { + return nullptr; + } +} + +const char* ConnectionGraph::trace_merged_message(PointsToNode* other) const { + if (_compile->directive()->TraceEscapeAnalysisOption) { + stringStream ss; + ss.print("is merged with other object: "); + other->dump_header(true, &ss); + return ss.as_string(); + } else { + return nullptr; + } +} + #endif void ConnectionGraph::record_for_optimizer(Node *n) { diff --git a/src/hotspot/share/opto/escape.hpp b/src/hotspot/share/opto/escape.hpp index aa02f979de28af04450f6cd1396326eabc06e971..20969920d774ec4c18b34d095bf6eef75b06ff3b 100644 --- a/src/hotspot/share/opto/escape.hpp +++ b/src/hotspot/share/opto/escape.hpp @@ -232,7 +232,8 @@ public: #ifndef PRODUCT NodeType node_type() const { return (NodeType)_type;} - void dump(bool print_state=true) const; + void dump(bool print_state=true, outputStream* out=tty, bool newline=true) const; + void dump_header(bool print_state=true, outputStream* out=tty) const; #endif }; @@ -429,21 +430,26 @@ private: int find_init_values_phantom(JavaObjectNode* ptn); // Set the escape state of an object and its fields. - void set_escape_state(PointsToNode* ptn, PointsToNode::EscapeState esc) { + void set_escape_state(PointsToNode* ptn, PointsToNode::EscapeState esc + NOT_PRODUCT(COMMA const char* reason)) { // Don't change non-escaping state of NULL pointer. if (ptn != null_obj) { if (ptn->escape_state() < esc) { + NOT_PRODUCT(trace_es_update_helper(ptn, esc, false, reason)); ptn->set_escape_state(esc); } if (ptn->fields_escape_state() < esc) { + NOT_PRODUCT(trace_es_update_helper(ptn, esc, true, reason)); ptn->set_fields_escape_state(esc); } } } - void set_fields_escape_state(PointsToNode* ptn, PointsToNode::EscapeState esc) { + void set_fields_escape_state(PointsToNode* ptn, PointsToNode::EscapeState esc + NOT_PRODUCT(COMMA const char* reason)) { // Don't change non-escaping state of NULL pointer. if (ptn != null_obj) { if (ptn->fields_escape_state() < esc) { + NOT_PRODUCT(trace_es_update_helper(ptn, esc, true, reason)); ptn->set_fields_escape_state(esc); } } @@ -569,6 +575,24 @@ private: // Compute the escape information bool compute_escape(); + void set_not_scalar_replaceable(PointsToNode* ptn NOT_PRODUCT(COMMA const char* reason)) const { +#ifndef PRODUCT + if (_compile->directive()->TraceEscapeAnalysisOption) { + assert(ptn != nullptr, "should not be null"); + ptn->dump_header(true); + tty->print_cr("is NSR. %s", reason); + } +#endif + ptn->set_scalar_replaceable(false); + } + +#ifndef PRODUCT + void trace_es_update_helper(PointsToNode* ptn, PointsToNode::EscapeState es, bool fields, const char* reason) const; + const char* trace_propagate_message(PointsToNode* from) const; + const char* trace_arg_escape_message(CallNode* call) const; + const char* trace_merged_message(PointsToNode* other) const; +#endif + public: ConnectionGraph(Compile *C, PhaseIterGVN *igvn, int iteration); diff --git a/src/hotspot/share/opto/ifg.cpp b/src/hotspot/share/opto/ifg.cpp index 9c1d1c52771b8e83fae00f261f464d95da569fcd..cee302f6ef1404e5d54b1443704f53dfe67a476e 100644 --- a/src/hotspot/share/opto/ifg.cpp +++ b/src/hotspot/share/opto/ifg.cpp @@ -37,6 +37,8 @@ #include "opto/memnode.hpp" #include "opto/opcodes.hpp" +#include + PhaseIFG::PhaseIFG( Arena *arena ) : Phase(Interference_Graph), _arena(arena) { } @@ -784,7 +786,7 @@ void PhaseChaitin::add_input_to_liveout(Block* b, Node* n, IndexSet* liveout, do assert(int_pressure.current_pressure() == count_int_pressure(liveout), "the int pressure is incorrect"); assert(float_pressure.current_pressure() == count_float_pressure(liveout), "the float pressure is incorrect"); } - assert(lrg._area >= 0.0, "negative spill area" ); + assert(lrg._area >= 0.0, "unexpected spill area value %g (rounding mode %x)", lrg._area, fegetround()); } } @@ -895,7 +897,7 @@ uint PhaseChaitin::build_ifg_physical( ResourceArea *a ) { if (g_isfinite(cost)) { lrg._area -= cost; } - assert(lrg._area >= 0.0, "negative spill area" ); + assert(lrg._area >= 0.0, "unexpected spill area value %g (rounding mode %x)", lrg._area, fegetround()); assign_high_score_to_immediate_copies(block, n, lrg, location + 1, last_inst); diff --git a/src/hotspot/share/opto/intrinsicnode.hpp b/src/hotspot/share/opto/intrinsicnode.hpp index ab8a834bb28ad7b8c8a7d01992baf1db3546a206..477842869c33ee1d7f80e450f66f39c1b24459c8 100644 --- a/src/hotspot/share/opto/intrinsicnode.hpp +++ b/src/hotspot/share/opto/intrinsicnode.hpp @@ -157,13 +157,13 @@ class AryEqNode: public StrIntrinsicNode { virtual const Type* bottom_type() const { return TypeInt::BOOL; } }; -//------------------------------HasNegatives--------------------------------- -class HasNegativesNode: public StrIntrinsicNode { +//------------------------------CountPositives------------------------------ +class CountPositivesNode: public StrIntrinsicNode { public: - HasNegativesNode(Node* control, Node* char_array_mem, Node* s1, Node* c1): + CountPositivesNode(Node* control, Node* char_array_mem, Node* s1, Node* c1): StrIntrinsicNode(control, char_array_mem, s1, c1, none) {}; virtual int Opcode() const; - virtual const Type* bottom_type() const { return TypeInt::BOOL; } + virtual const Type* bottom_type() const { return TypeInt::POS; } }; diff --git a/src/hotspot/share/opto/lcm.cpp b/src/hotspot/share/opto/lcm.cpp index fe799dd98475dc4549cbf8e0b9fba58faeea839f..97740e90a295cb72b498333740cbaa6d899b517d 100644 --- a/src/hotspot/share/opto/lcm.cpp +++ b/src/hotspot/share/opto/lcm.cpp @@ -203,7 +203,7 @@ void PhaseCFG::implicit_null_check(Block* block, Node *proj, Node *val, int allo case Op_StrInflatedCopy: case Op_StrCompressedCopy: case Op_EncodeISOArray: - case Op_HasNegatives: + case Op_CountPositives: // Not a legit memory op for implicit null check regardless of // embedded loads continue; diff --git a/src/hotspot/share/opto/library_call.cpp b/src/hotspot/share/opto/library_call.cpp index 31d56fcd70ea348b974a6f4193a8814c009d0983..2f7c7fdc84c91005e1d7afa05397c00f17245867 100644 --- a/src/hotspot/share/opto/library_call.cpp +++ b/src/hotspot/share/opto/library_call.cpp @@ -617,8 +617,8 @@ bool LibraryCallKit::try_to_inline(int predicate) { case vmIntrinsics::_isCompileConstant: return inline_isCompileConstant(); - case vmIntrinsics::_hasNegatives: - return inline_hasNegatives(); + case vmIntrinsics::_countPositives: + return inline_countPositives(); case vmIntrinsics::_fmaD: case vmIntrinsics::_fmaF: @@ -1011,13 +1011,13 @@ bool LibraryCallKit::inline_array_equals(StrIntrinsicNode::ArgEnc ae) { return true; } -//------------------------------inline_hasNegatives------------------------------ -bool LibraryCallKit::inline_hasNegatives() { +//------------------------------inline_countPositives------------------------------ +bool LibraryCallKit::inline_countPositives() { if (too_many_traps(Deoptimization::Reason_intrinsic)) { return false; } - assert(callee()->signature()->size() == 3, "hasNegatives has 3 parameters"); + assert(callee()->signature()->size() == 3, "countPositives has 3 parameters"); // no receiver since it is static method Node* ba = argument(0); Node* offset = argument(1); @@ -1031,7 +1031,7 @@ bool LibraryCallKit::inline_hasNegatives() { return true; } Node* ba_start = array_element_address(ba, offset, T_BYTE); - Node* result = new HasNegativesNode(control(), memory(TypeAryPtr::BYTES), ba_start, len); + Node* result = new CountPositivesNode(control(), memory(TypeAryPtr::BYTES), ba_start, len); set_result(_gvn.transform(result)); return true; } @@ -1092,7 +1092,6 @@ bool LibraryCallKit::inline_preconditions_checkIndex(BasicType bt) { result = _gvn.transform(result); set_result(result); replace_in_map(index, result); - clear_upper_avx(); return true; } diff --git a/src/hotspot/share/opto/library_call.hpp b/src/hotspot/share/opto/library_call.hpp index eca3e70bb5ae6966d9feea296e48dee3ec08c350..d8f86233d6be92e712db9ca4062ce69072532044 100644 --- a/src/hotspot/share/opto/library_call.hpp +++ b/src/hotspot/share/opto/library_call.hpp @@ -296,7 +296,7 @@ class LibraryCallKit : public GraphKit { bool inline_updateBytesAdler32(); bool inline_updateByteBufferAdler32(); bool inline_multiplyToLen(); - bool inline_hasNegatives(); + bool inline_countPositives(); bool inline_squareToLen(); bool inline_mulAdd(); bool inline_montgomeryMultiply(); diff --git a/src/hotspot/share/opto/loopPredicate.cpp b/src/hotspot/share/opto/loopPredicate.cpp index 584df76315629c22386be971866e94aca3445ca1..ee88d0fabf42255a06689d1e92ce4d01db48564c 100644 --- a/src/hotspot/share/opto/loopPredicate.cpp +++ b/src/hotspot/share/opto/loopPredicate.cpp @@ -759,7 +759,7 @@ bool IdealLoopTree::is_range_check_if(IfNode *iff, PhaseIdealLoop *phase, BasicT } scale = 0; offset = NULL; - if (!phase->is_scaled_iv_plus_offset(cmp->in(1), iv, &scale, &offset, bt)) { + if (!phase->is_scaled_iv_plus_offset(cmp->in(1), iv, bt, &scale, &offset)) { return false; } return true; diff --git a/src/hotspot/share/opto/loopTransform.cpp b/src/hotspot/share/opto/loopTransform.cpp index 21dab9335c01d70e18ea6e0246d39879dd67655a..dc9c2064ed9e126e80123ade5d5ca5f70628b5c5 100644 --- a/src/hotspot/share/opto/loopTransform.cpp +++ b/src/hotspot/share/opto/loopTransform.cpp @@ -828,7 +828,7 @@ bool IdealLoopTree::policy_maximally_unroll(PhaseIdealLoop* phase) const { case Op_StrIndexOfChar: case Op_EncodeISOArray: case Op_AryEq: - case Op_HasNegatives: { + case Op_CountPositives: { return false; } #if INCLUDE_RTM_OPT @@ -956,6 +956,8 @@ bool IdealLoopTree::policy_unroll(PhaseIdealLoop *phase) { (stride_con < 0 && ((max_jint + stride_con) < limit_type->_lo))) return false; // overflow + // Rudimentary cost model to estimate loop unrolling + // factor. // Adjust body_size to determine if we unroll or not uint body_size = _body.size(); // Key test to unroll loop in CRC32 java code @@ -968,13 +970,18 @@ bool IdealLoopTree::policy_unroll(PhaseIdealLoop *phase) { case Op_ModL: body_size += 30; break; case Op_DivL: body_size += 30; break; case Op_MulL: body_size += 10; break; + case Op_PopCountVI: + case Op_PopCountVL: { + const TypeVect* vt = n->bottom_type()->is_vect(); + body_size += Matcher::vector_op_pre_select_sz_estimate(n->Opcode(), vt->element_basic_type(), vt->length()); + } break; case Op_StrComp: case Op_StrEquals: case Op_StrIndexOf: case Op_StrIndexOfChar: case Op_EncodeISOArray: case Op_AryEq: - case Op_HasNegatives: { + case Op_CountPositives: { // Do not unroll a loop with String intrinsics code. // String intrinsics are large and have loops. return false; @@ -1121,18 +1128,18 @@ bool IdealLoopTree::policy_range_check(PhaseIdealLoop* phase, bool provisional, continue; // not RC } Node *cmp = bol->in(1); - Node *rc_exp = cmp->in(1); - Node *limit = cmp->in(2); if (provisional) { // Try to pattern match with either cmp inputs, do not check // whether one of the inputs is loop independent as it may not // have had a chance to be hoisted yet. - if (!phase->is_scaled_iv_plus_offset(cmp->in(1), trip_counter, NULL, NULL, bt) && - !phase->is_scaled_iv_plus_offset(cmp->in(2), trip_counter, NULL, NULL, bt)) { + if (!phase->is_scaled_iv_plus_offset(cmp->in(1), trip_counter, bt, NULL, NULL) && + !phase->is_scaled_iv_plus_offset(cmp->in(2), trip_counter, bt, NULL, NULL)) { continue; } } else { + Node *rc_exp = cmp->in(1); + Node *limit = cmp->in(2); Node *limit_c = phase->get_ctrl(limit); if (limit_c == phase->C->top()) { return false; // Found dead test on live IF? No RCE! @@ -1147,7 +1154,7 @@ bool IdealLoopTree::policy_range_check(PhaseIdealLoop* phase, bool provisional, } } - if (!phase->is_scaled_iv_plus_offset(rc_exp, trip_counter, NULL, NULL, bt)) { + if (!phase->is_scaled_iv_plus_offset(rc_exp, trip_counter, bt, NULL, NULL)) { continue; } } @@ -1947,6 +1954,12 @@ bool IdealLoopTree::is_invariant(Node* n) const { } void PhaseIdealLoop::update_main_loop_skeleton_predicates(Node* ctrl, CountedLoopNode* loop_head, Node* init, int stride_con) { + if (init->Opcode() == Op_CastII) { + // skip over the cast added by PhaseIdealLoop::cast_incr_before_loop() when pre/post/main loops are created because + // it can get in the way of type propagation + assert(((CastIINode*)init)->carry_dependency() && loop_head->skip_predicates() == init->in(0), "casted iv phi from pre loop expected"); + init = init->in(1); + } // Search for skeleton predicates and update them according to the new stride Node* entry = ctrl; Node* prev_proj = ctrl; @@ -2522,127 +2535,202 @@ void PhaseIdealLoop::add_constraint(jlong stride_con, jlong scale_con, Node* off } } +//----------------------------------is_iv------------------------------------ +// Return true if exp is the value (of type bt) of the given induction var. +// This grammar of cases is recognized, where X is I|L according to bt: +// VIV[iv] = iv | (CastXX VIV[iv]) | (ConvI2X VIV[iv]) bool PhaseIdealLoop::is_iv(Node* exp, Node* iv, BasicType bt) { - if (exp == iv) { + exp = exp->uncast(); + if (exp == iv && iv->bottom_type()->isa_integer(bt)) { return true; } - if (bt == T_LONG && iv->bottom_type()->isa_int() && exp->Opcode() == Op_ConvI2L && exp->in(1) == iv) { + if (bt == T_LONG && iv->bottom_type()->isa_int() && exp->Opcode() == Op_ConvI2L && exp->in(1)->uncast() == iv) { return true; } return false; } //------------------------------is_scaled_iv--------------------------------- -// Return true if exp is a constant times an induction var -bool PhaseIdealLoop::is_scaled_iv(Node* exp, Node* iv, jlong* p_scale, BasicType bt, bool* converted) { - exp = exp->uncast(); - assert(bt == T_INT || bt == T_LONG, "unexpected int type"); - if (is_iv(exp, iv, bt)) { +// Return true if exp is a constant times the given induction var (of type bt). +// The multiplication is either done in full precision (exactly of type bt), +// or else bt is T_LONG but iv is scaled using 32-bit arithmetic followed by a ConvI2L. +// This grammar of cases is recognized, where X is I|L according to bt: +// SIV[iv] = VIV[iv] | (CastXX SIV[iv]) +// | (MulX VIV[iv] ConX) | (MulX ConX VIV[iv]) +// | (LShiftX VIV[iv] ConI) +// | (ConvI2L SIV[iv]) -- a "short-scale" can occur here; note recursion +// | (SubX 0 SIV[iv]) -- same as MulX(iv, -scale); note recursion +// VIV[iv] = [either iv or its value converted; see is_iv() above] +// On success, the constant scale value is stored back to *p_scale. +// The value (*p_short_scale) reports if such a ConvI2L conversion was present. +bool PhaseIdealLoop::is_scaled_iv(Node* exp, Node* iv, BasicType bt, jlong* p_scale, bool* p_short_scale, int depth) { + BasicType exp_bt = bt; + exp = exp->uncast(); //strip casts + assert(exp_bt == T_INT || exp_bt == T_LONG, "unexpected int type"); + if (is_iv(exp, iv, exp_bt)) { if (p_scale != NULL) { *p_scale = 1; } + if (p_short_scale != NULL) { + *p_short_scale = false; + } return true; } - if (bt == T_LONG && iv->bottom_type()->isa_int() && exp->Opcode() == Op_ConvI2L) { + if (exp_bt == T_LONG && iv->bottom_type()->isa_int() && exp->Opcode() == Op_ConvI2L) { exp = exp->in(1); - bt = T_INT; - if (converted != NULL) { - *converted = true; - } + exp_bt = T_INT; } int opc = exp->Opcode(); + int which = 0; // this is which subexpression we find the iv in // Can't use is_Mul() here as it's true for AndI and AndL - if (opc == Op_Mul(bt)) { - if (is_iv(exp->in(1)->uncast(), iv, bt) && exp->in(2)->is_Con()) { + if (opc == Op_Mul(exp_bt)) { + if ((is_iv(exp->in(which = 1), iv, exp_bt) && exp->in(2)->is_Con()) || + (is_iv(exp->in(which = 2), iv, exp_bt) && exp->in(1)->is_Con())) { + Node* factor = exp->in(which == 1 ? 2 : 1); // the other argument + jlong scale = factor->find_integer_as_long(exp_bt, 0); + if (scale == 0) { + return false; // might be top + } if (p_scale != NULL) { - *p_scale = exp->in(2)->get_integer_as_long(bt); + *p_scale = scale; + } + if (p_short_scale != NULL) { + // (ConvI2L (MulI iv K)) can be 64-bit linear if iv is kept small enough... + *p_short_scale = (exp_bt != bt && scale != 1); } return true; } - if (is_iv(exp->in(2)->uncast(), iv, bt) && exp->in(1)->is_Con()) { + } else if (opc == Op_LShift(exp_bt)) { + if (is_iv(exp->in(1), iv, exp_bt) && exp->in(2)->is_Con()) { + jint shift_amount = exp->in(2)->find_int_con(min_jint); + if (shift_amount == min_jint) { + return false; // might be top + } + jlong scale; + if (exp_bt == T_INT) { + scale = java_shift_left((jint)1, (juint)shift_amount); + } else if (exp_bt == T_LONG) { + scale = java_shift_left((jlong)1, (julong)shift_amount); + } if (p_scale != NULL) { - *p_scale = exp->in(1)->get_integer_as_long(bt); + *p_scale = scale; + } + if (p_short_scale != NULL) { + // (ConvI2L (MulI iv K)) can be 64-bit linear if iv is kept small enough... + *p_short_scale = (exp_bt != bt && scale != 1); } return true; } - } else if (opc == Op_LShift(bt)) { - if (is_iv(exp->in(1)->uncast(), iv, bt) && exp->in(2)->is_Con()) { + } else if (opc == Op_Sub(exp_bt) && + exp->in(1)->find_integer_as_long(exp_bt, -1) == 0) { + jlong scale = 0; + if (depth == 0 && is_scaled_iv(exp->in(2), iv, exp_bt, &scale, p_short_scale, depth + 1)) { + // SubX(0, iv*K) => iv*(-K) + if (scale == min_signed_integer(exp_bt)) { + // This should work even if -K overflows, but let's not. + return false; + } + scale = java_multiply(scale, (jlong)-1); if (p_scale != NULL) { - jint shift_amount = exp->in(2)->get_int(); - if (bt == T_INT) { - *p_scale = java_shift_left((jint)1, (juint)shift_amount); - } else if (bt == T_LONG) { - *p_scale = java_shift_left((jlong)1, (julong)shift_amount); - } + *p_scale = scale; + } + if (p_short_scale != NULL) { + // (ConvI2L (MulI iv K)) can be 64-bit linear if iv is kept small enough... + *p_short_scale = *p_short_scale || (exp_bt != bt && scale != 1); } return true; } } + // We could also recognize (iv*K1)*K2, even with overflow, but let's not. return false; } -//-----------------------------is_scaled_iv_plus_offset------------------------------ -// Return true if exp is a simple induction variable expression: k1*iv + (invar + k2) -bool PhaseIdealLoop::is_scaled_iv_plus_offset(Node* exp, Node* iv, jlong* p_scale, Node** p_offset, BasicType bt, bool* converted, int depth) { +//-------------------------is_scaled_iv_plus_offset-------------------------- +// Return true if exp is a simple linear transform of the given induction var. +// The scale must be constant and the addition tree (if any) must be simple. +// This grammar of cases is recognized, where X is I|L according to bt: +// +// OIV[iv] = SIV[iv] | (CastXX OIV[iv]) +// | (AddX SIV[iv] E) | (AddX E SIV[iv]) +// | (SubX SIV[iv] E) | (SubX E SIV[iv]) +// SSIV[iv] = (ConvI2X SIV[iv]) -- a "short scale" might occur here +// SIV[iv] = [a possibly scaled value of iv; see is_scaled_iv() above] +// +// On success, the constant scale value is stored back to *p_scale unless null. +// Likewise, the addend (perhaps a synthetic AddX node) is stored to *p_offset. +// Also, (*p_short_scale) reports if a ConvI2L conversion was seen after a MulI, +// meaning bt is T_LONG but iv was scaled using 32-bit arithmetic. +// To avoid looping, the match is depth-limited, and so may fail to match the grammar to complex expressions. +bool PhaseIdealLoop::is_scaled_iv_plus_offset(Node* exp, Node* iv, BasicType bt, jlong* p_scale, Node** p_offset, bool* p_short_scale, int depth) { assert(bt == T_INT || bt == T_LONG, "unexpected int type"); - if (is_scaled_iv(exp, iv, p_scale, bt, converted)) { + jlong scale = 0; // to catch result from is_scaled_iv() + BasicType exp_bt = bt; + exp = exp->uncast(); + if (is_scaled_iv(exp, iv, exp_bt, &scale, p_short_scale)) { + if (p_scale != NULL) { + *p_scale = scale; + } if (p_offset != NULL) { - Node *zero = _igvn.integercon(0, bt); + Node *zero = _igvn.zerocon(bt); set_ctrl(zero, C->root()); *p_offset = zero; } return true; } - exp = exp->uncast(); + if (exp_bt != bt) { + // We would now be matching inputs like (ConvI2L exp:(AddI (MulI iv S) E)). + // It's hard to make 32-bit arithmetic linear if it overflows. Although we do + // cope with overflowing multiplication by S, it would be even more work to + // handle overflowing addition of E. So we bail out here on ConvI2L input. + return false; + } int opc = exp->Opcode(); - if (opc == Op_Add(bt)) { - if (is_scaled_iv(exp->in(1), iv, p_scale, bt, converted)) { + int which = 0; // this is which subexpression we find the iv in + Node* offset = NULL; + if (opc == Op_Add(exp_bt)) { + // Check for a scaled IV in (AddX (MulX iv S) E) or (AddX E (MulX iv S)). + if (is_scaled_iv(exp->in(which = 1), iv, bt, &scale, p_short_scale) || + is_scaled_iv(exp->in(which = 2), iv, bt, &scale, p_short_scale)) { + offset = exp->in(which == 1 ? 2 : 1); // the other argument + if (p_scale != NULL) { + *p_scale = scale; + } if (p_offset != NULL) { - *p_offset = exp->in(2); + *p_offset = offset; } return true; } - if (is_scaled_iv(exp->in(2), iv, p_scale, bt, converted)) { - if (p_offset != NULL) { - *p_offset = exp->in(1); - } + // Check for more addends, like (AddX (AddX (MulX iv S) E1) E2), etc. + if (is_scaled_iv_plus_extra_offset(exp->in(1), exp->in(2), iv, bt, p_scale, p_offset, p_short_scale, depth) || + is_scaled_iv_plus_extra_offset(exp->in(2), exp->in(1), iv, bt, p_scale, p_offset, p_short_scale, depth)) { return true; } - if (exp->in(2)->is_Con()) { - Node* offset2 = NULL; - if (depth < 2 && - is_scaled_iv_plus_offset(exp->in(1), iv, p_scale, - p_offset != NULL ? &offset2 : NULL, bt, converted, depth+1)) { - if (p_offset != NULL) { - Node *ctrl_off2 = get_ctrl(offset2); - Node* offset = AddNode::make(offset2, exp->in(2), bt); - register_new_node(offset, ctrl_off2); - *p_offset = offset; + } else if (opc == Op_Sub(exp_bt)) { + if (is_scaled_iv(exp->in(which = 1), iv, bt, &scale, p_short_scale) || + is_scaled_iv(exp->in(which = 2), iv, bt, &scale, p_short_scale)) { + // Match (SubX SIV[iv] E) as if (AddX SIV[iv] (SubX 0 E)), and + // match (SubX E SIV[iv]) as if (AddX E (SubX 0 SIV[iv])). + offset = exp->in(which == 1 ? 2 : 1); // the other argument + if (which == 2) { + // We can't handle a scale of min_jint (or min_jlong) here as -1 * min_jint = min_jint + if (scale == min_signed_integer(bt)) { + return false; // cannot negate the scale of the iv } - return true; + scale = java_multiply(scale, (jlong)-1); } - } - } else if (opc == Op_Sub(bt)) { - if (is_scaled_iv(exp->in(1), iv, p_scale, bt, converted)) { - if (p_offset != NULL) { - Node *zero = _igvn.integercon(0, bt); - set_ctrl(zero, C->root()); - Node *ctrl_off = get_ctrl(exp->in(2)); - Node* offset = SubNode::make(zero, exp->in(2), bt); - register_new_node(offset, ctrl_off); - *p_offset = offset; + if (p_scale != NULL) { + *p_scale = scale; } - return true; - } - if (is_scaled_iv(exp->in(2), iv, p_scale, bt, converted)) { if (p_offset != NULL) { - // We can't handle a scale of min_jint (or min_jlong) here as -1 * min_jint = min_jint - if (*p_scale == min_signed_integer(bt)) { - return false; + if (which == 1) { // must negate the extracted offset + Node *zero = _igvn.integercon(0, exp_bt); + set_ctrl(zero, C->root()); + Node *ctrl_off = get_ctrl(offset); + offset = SubNode::make(zero, offset, exp_bt); + register_new_node(offset, ctrl_off); } - *p_scale *= -1; - *p_offset = exp->in(1); + *p_offset = offset; } return true; } @@ -2650,6 +2738,33 @@ bool PhaseIdealLoop::is_scaled_iv_plus_offset(Node* exp, Node* iv, jlong* p_scal return false; } +// Helper for is_scaled_iv_plus_offset(), not called separately. +// The caller encountered (AddX exp1 offset3) or (AddX offset3 exp1). +// Here, exp1 is inspected to see if it is a simple linear transform of iv. +// If so, the offset3 is combined with any other offset2 from inside exp1. +bool PhaseIdealLoop::is_scaled_iv_plus_extra_offset(Node* exp1, Node* offset3, Node* iv, + BasicType bt, + jlong* p_scale, Node** p_offset, + bool* p_short_scale, int depth) { + // By the time we reach here, it is unlikely that exp1 is a simple iv*K. + // If is a linear iv transform, it is probably an add or subtract. + // Let's collect the internal offset2 from it. + Node* offset2 = NULL; + if (offset3->is_Con() && + depth < 2 && + is_scaled_iv_plus_offset(exp1, iv, bt, p_scale, + &offset2, p_short_scale, depth+1)) { + if (p_offset != NULL) { + Node* ctrl_off2 = get_ctrl(offset2); + Node* offset = AddNode::make(offset2, offset3, bt); + register_new_node(offset, ctrl_off2); + *p_offset = offset; + } + return true; + } + return false; +} + // Same as PhaseIdealLoop::duplicate_predicates() but for range checks // eliminated by iteration splitting. Node* PhaseIdealLoop::add_range_check_predicate(IdealLoopTree* loop, CountedLoopNode* cl, diff --git a/src/hotspot/share/opto/loopnode.cpp b/src/hotspot/share/opto/loopnode.cpp index 68973406f865b8a19938521ee2fbb5c86da30714..f08b1d46b1c809426f1de6e50ddcf19116c3f905 100644 --- a/src/hotspot/share/opto/loopnode.cpp +++ b/src/hotspot/share/opto/loopnode.cpp @@ -690,8 +690,7 @@ SafePointNode* PhaseIdealLoop::find_safepoint(Node* back_control, Node* x, Ideal Node* mem = safepoint->in(TypeFunc::Memory); - // We can only use that safepoint if there's not side effect - // between the backedge and the safepoint. + // We can only use that safepoint if there's no side effect between the backedge and the safepoint. // mm is used for book keeping MergeMemNode* mm = NULL; @@ -853,7 +852,10 @@ bool PhaseIdealLoop::create_loop_nest(IdealLoopTree* loop, Node_List &old_new) { SafePointNode* safepoint; if (bt == T_INT && head->as_CountedLoop()->is_strip_mined()) { // Loop is strip mined: use the safepoint of the outer strip mined loop - strip_mined_nest_back_to_counted_loop(loop, head, back_control, exit_test, safepoint); + OuterStripMinedLoopNode* outer_loop = head->as_CountedLoop()->outer_loop(); + safepoint = outer_loop->outer_safepoint(); + outer_loop->transform_to_counted_loop(&_igvn, this); + exit_test = head->loopexit(); } else { safepoint = find_safepoint(back_control, x, loop); } @@ -1059,73 +1061,8 @@ bool PhaseIdealLoop::create_loop_nest(IdealLoopTree* loop, Node_List &old_new) { return true; } -// Convert the strip mined loop nest back to a single loop with the safepoint right before the loop exit test -void PhaseIdealLoop::strip_mined_nest_back_to_counted_loop(IdealLoopTree* loop, const BaseCountedLoopNode* head, - Node* back_control, IfNode*& exit_test, - SafePointNode*& safepoint) { - CountedLoopNode* cl = head->as_CountedLoop(); - cl->verify_strip_mined(1); - safepoint = cl->outer_safepoint(); - CountedLoopEndNode* cle = cl->loopexit(); - OuterStripMinedLoopNode* outer_head = cl->outer_loop(); - OuterStripMinedLoopEndNode* outer_end = cl->outer_loop_end(); - - cl->clear_strip_mined(); - - _igvn.replace_input_of(cl, LoopNode::EntryControl, outer_head->in(LoopNode::EntryControl)); - _igvn.replace_input_of(outer_head, LoopNode::EntryControl, C->top()); - set_idom(cl, cl->in(LoopNode::EntryControl), dom_depth(cl)); - - Node* exit_bol = cle->in(1); - Node *zero = _igvn.intcon(0); - set_ctrl(zero, C->root()); - _igvn.replace_input_of(cle, 1, zero); - - _igvn.replace_input_of(outer_end, 1, exit_bol); - - assert(outer_head->in(LoopNode::LoopBackControl)->in(0) == outer_end, ""); - _igvn.replace_input_of(outer_head->in(LoopNode::LoopBackControl), 0, C->top()); - _igvn.replace_input_of(back_control, 0, outer_end); - set_idom(back_control, outer_end, dom_depth(outer_end) + 1); - - Unique_Node_List wq; - wq.push(safepoint); - - IdealLoopTree* outer_loop_ilt = get_loop(outer_head); - - for (uint i = 0; i < wq.size(); i++) { - Node* n = wq.at(i); - for (uint j = 0; j < n->req(); ++j) { - Node* in = n->in(j); - if (in == NULL || in->is_CFG()) { - continue; - } - if (get_loop(get_ctrl(in)) != outer_loop_ilt) { - continue; - } - assert(!loop->_body.contains(in), ""); - loop->_body.push(in); - wq.push(in); - } - } - - set_loop(outer_end, loop); - loop->_body.push(outer_end); - set_loop(safepoint, loop); - loop->_body.push(safepoint); - set_loop(safepoint->in(0), loop); - loop->_body.push(safepoint->in(0)); - - exit_test = outer_end; - - outer_loop_ilt->_tail = C->top(); -} - int PhaseIdealLoop::extract_long_range_checks(const IdealLoopTree* loop, jlong stride_con, int iters_limit, PhiNode* phi, Node_List& range_checks) { - if (stride_con < 0) { // only for stride_con > 0 && scale > 0 for now - return iters_limit; - } const jlong min_iters = 2; jlong reduced_iters_limit = iters_limit; jlong original_iters_limit = iters_limit; @@ -1140,7 +1077,6 @@ int PhaseIdealLoop::extract_long_range_checks(const IdealLoopTree* loop, jlong s RangeCheckNode* rc = c->in(0)->as_RangeCheck(); if (loop->is_range_check_if(rc, this, T_LONG, phi, range, offset, scale) && loop->is_invariant(range) && loop->is_invariant(offset) && - scale > 0 && // only for stride_con > 0 && scale > 0 for now original_iters_limit / ABS(scale * stride_con) >= min_iters) { reduced_iters_limit = MIN2(reduced_iters_limit, original_iters_limit/ABS(scale)); range_checks.push(c); @@ -1155,27 +1091,29 @@ int PhaseIdealLoop::extract_long_range_checks(const IdealLoopTree* loop, jlong s // One execution of the inner loop covers a sub-range of the entire iteration range of the loop: [A,Z), aka [A=init, // Z=limit). If the loop has at least one trip (which is the case here), the iteration variable i always takes A as its // first value, followed by A+S (S is the stride), next A+2S, etc. The limit is exclusive, so that the final value B of -// i is never Z. It will be B=Z-1 if S=1, or B=Z+1 if S=-1. If |S|>1 the formula for the last value requires a floor -// operation, specifically B=floor((Z-sgn(S)-A)/S)*S+A. Thus i ranges as i:[A,B] or i:[A,Z) or i:[A,Z-U) for some U 0) to simplify the logic for clamping 32-bit bounds (L_2, R_2). -// For restrictions on S and K, see the guards in extract_long_range_checks. +// If |S|>1 the formula for the last value B would require a floor operation, specifically B=floor((Z-sgn(S)-A)/S)*S+A, +// which is B=Z-sgn(S)U for some U in [1,|S|]. So when S>0, i ranges as i:[A,Z) or i:[A,B=Z-U], or else (in reverse) +// as i:(Z,A] or i:[B=Z+U,A]. It will become important to reason about this inclusive range [A,B] or [B,A]. // Within the loop there may be many range checks. Each such range check (R.C.) is of the form 0 <= i*K+L < R, where K // is a scale factor applied to the loop iteration variable i, and L is some offset; K, L, and R are loop-invariant. -// Because R is never negative, this check can always be simplified to an unsigned check i*K+L 0), where the limit is +// chosen to prevent various cases of 32-bit overflow (including multiplications j*K below). In the sub-loop the +// logical value i is offset from j by a 64-bit constant C, so i ranges in i:C+[0,Z_2). -// The union of all the C+[0,Z_2) ranges from the sub-loops must be identical to the whole range [A,B]. Assuming S>0, -// the first C must be A itself, and the next C value is the previous C+Z_2. In each sub-loop, j counts up from zero -// and exits just before i=C+Z_2. +// For S<0, j ranges (in reverse!) through j:[-|B_2|,0] or (-|Z_2|,0]. For either sign of S, we can say i=j+C and j +// ranges through 32-bit ranges [A_2,B_2] or [B_2,A_2] (A_2=0 of course). -// (N.B. If S<0 the formulas are different, because all the loops count downward.) +// The disjoint union of all the C+[A_2,B_2] ranges from the sub-loops must be identical to the whole range [A,B]. +// Assuming S>0, the first C must be A itself, and the next C value is the previous C+B_2, plus S. If |S|=1, the next +// C value is also the previous C+Z_2. In each sub-loop, j counts from j=A_2=0 and i counts from C+0 and exits at +// j=B_2 (i=C+B_2), just before it gets to i=C+Z_2. Both i and j count up (from C and 0) if S>0; otherwise they count +// down (from C and 0 again). // Returning to range checks, we see that each i*K+L 0 and K>0), Q_min=A_2*K+Q and Q_max=Q (if S<0 and K>0), +// Q_min=B_2*K+Q and Q_max=Q if (S>0 and K<0), Q_min=Q and Q_max=A_2*K+Q (if S<0 and K<0) -// N.B. If (S*K)<0 then the formulas for Q_min and Q_max may differ; the values may need to be swapped and adjusted to -// the correct type of bound (inclusive or exclusive). +// Note that the first R.C. value is always Q=(S*K>0 ? Q_min : Q_max). Also Q_{min,max} = Q + {min,max}(A_2*K,B_2*K). +// If S*K>0 then, as the loop iterations progress, each R.C. value i*K+L = j*K+Q goes up from Q=Q_min towards Q_max. +// If S*K<0 then j*K+Q starts at Q=Q_max and goes down towards Q_min. // Case A: Some Negatives (but no overflow). // Number line: // |s64_min . . . 0 . . . s64_max| // | . Q_min..Q_max . 0 . . . . | s64 negative +// | . . . . R=0 R< R< R< R< | (against R values) // | . . . Q_min..0..Q_max . . . | small mixed +// | . . . . R R R< R< R< | (against R values) // -// if Q_min Q_max+1) are reduced to max(0,Q_max+1). They are marked on the number line as R<. +// +// So, if Q_min 0 (R.C.E. steps upward) +// j*K + s32_trunc(Q_max) R R R< R< | (against R values) // | . . . . 0 . Q_min..Q_max . | s64 positive +// | . . . . R> R> R R R< | (against R values) +// +// R values which are out of range (Q_max+1) are reduced as marked: R> up to Q_min, R< down to Q_max+1. +// Then the whole comparison is shifted left by Q_min, so it can take place at zero, which is a nice 32-bit value. // -// if both Q_min, Q_max >=s64 0, then use this test: -// j*K + 0 =s64 0, then use this test: +// j*K + 0 0 +// More generally: +// j*K + Q - Q_min R> R> R> R | (against R values) // -// if Q_min >=s64 0 but Q_max s64 Q_max+1, even though the mathematical values of Q_min and Q_max+1 are correctly ordered. +// The formulas from the previous case can be used, except that the bad upper bound Q_max is replaced by max_jlong. +// (In fact, we could use any replacement bound from R to max_jlong inclusive, as the input to the clamp function.) // -// Here the clamp function is a simple 64-bit min/max: -// clamp(X, L, H) := max(L, min(X, H)) +// So if Q_min >=s64 0 but Q_max+1 0 +// More generally: +// j*K + Q - Q_min H, it returns L not H. // -// Tests above can be merged into a single one: -// L_clamp = Q_min < 0 ? 0 : Q_min -// H_clamp = Q_max < Q_min ? R : Q_max -// j*K + Q_min - L_clamp = 0 ? max_jlong : Q_max+1 +// Q_first = Q = (S*K>0 ? Q_min : Q_max) = (C*K+L) +// R_clamp = clamp(R, L_clamp, H_clamp) --reduced dynamic range +// replacement R.C.: +// j*K + Q_first - L_clamp root()); + Node* int_zero = _igvn.intcon(0); + set_ctrl(int_zero, this->C->root()); + Node* long_one = _igvn.longcon(1); + set_ctrl(long_one, this->C->root()); + Node* int_stride = _igvn.intcon(checked_cast(stride_con)); + set_ctrl(int_stride, this->C->root()); for (uint i = 0; i < range_checks.size(); i++) { ProjNode* proj = range_checks.at(i)->as_Proj(); @@ -1267,8 +1244,8 @@ void PhaseIdealLoop::transform_long_range_checks(int stride_con, const Node_List // could be shared and have already been taken care of continue; } - bool converted = false; - bool ok = is_scaled_iv_plus_offset(rc_cmp->in(1), iv_add, &scale, &offset, T_LONG, &converted); + bool short_scale = false; + bool ok = is_scaled_iv_plus_offset(rc_cmp->in(1), iv_add, T_LONG, &scale, &offset, &short_scale); assert(ok, "inconsistent: was tested before"); Node* range = rc_cmp->in(2); Node* c = rc->in(0); @@ -1280,33 +1257,33 @@ void PhaseIdealLoop::transform_long_range_checks(int stride_con, const Node_List Node* L = offset; - if (converted) { + if (short_scale) { // This converts: - // i*K + L (long)max_jint and < R - // and so i*(long)K + L u64 (long)max_jint and still is root()); Node* max_range = new AddLNode(max_jint_plus_one_long, L); @@ -1316,26 +1293,38 @@ void PhaseIdealLoop::transform_long_range_checks(int stride_con, const Node_List } Node* C = outer_phi; - Node* Z_2 = new ConvI2LNode(inner_iters_actual_int, TypeLong::LONG); - register_new_node(Z_2, entry_control); // Start with 64-bit values: // i*K + L C, int_zero, inner_iters_actual_int, int_stride); + register_new_node(B_2, entry_control); + B_2 = new SubINode(B_2, int_stride); + register_new_node(B_2, entry_control); + B_2 = new ConvI2LNode(B_2); + register_new_node(B_2, entry_control); + + Node* Q_max = new MulLNode(B_2, K); register_new_node(Q_max, entry_control); - Q_max = new AddLNode(Q_max, L_2); + Q_max = new AddLNode(Q_max, Q_first); register_new_node(Q_max, entry_control); + if (scale * stride_con < 0) { + swap(Q_min, Q_max); + } + // Now, mathematically, Q_max > Q_min, and they are close enough so that (Q_max-Q_min) fits in 32 bits. + // L_clamp = Q_min < 0 ? 0 : Q_min Node* Q_min_cmp = new CmpLNode(Q_min, long_zero); register_new_node(Q_min_cmp, entry_control); @@ -1343,38 +1332,53 @@ void PhaseIdealLoop::transform_long_range_checks(int stride_con, const Node_List register_new_node(Q_min_bool, entry_control); Node* L_clamp = new CMoveLNode(Q_min_bool, Q_min, long_zero, TypeLong::LONG); register_new_node(L_clamp, entry_control); + // (This could also be coded bitwise as L_clamp = Q_min & ~(Q_min>>63).) - // H_clamp = Q_max < Q_min ? R : Q_max - Node* Q_max_cmp = new CmpLNode(Q_max, Q_min); + Node* Q_max_plus_one = new AddLNode(Q_max, long_one); + register_new_node(Q_max_plus_one, entry_control); + + // H_clamp = Q_max+1 < Q_min ? max_jlong : Q_max+1 + // (Because Q_min and Q_max are close, the overflow check could also be encoded as Q_max+1 < 0 & Q_min >= 0.) + Node* max_jlong_long = _igvn.longcon(max_jlong); + set_ctrl(max_jlong_long, this->C->root()); + Node* Q_max_cmp = new CmpLNode(Q_max_plus_one, Q_min); register_new_node(Q_max_cmp, entry_control); Node* Q_max_bool = new BoolNode(Q_max_cmp, BoolTest::lt); register_new_node(Q_max_bool, entry_control); - Node* H_clamp = new CMoveLNode(Q_max_bool, Q_max, R, TypeLong::LONG); + Node* H_clamp = new CMoveLNode(Q_max_bool, Q_max_plus_one, max_jlong_long, TypeLong::LONG); register_new_node(H_clamp, entry_control); + // (This could also be coded bitwise as H_clamp = ((Q_max+1)<<1 | M)>>>1 where M = (Q_max+1)>>63 & ~Q_min>>63.) // R_2 = clamp(R, L_clamp, H_clamp) - L_clamp - // that is: R_2 = clamp(R, L_clamp, H_clamp) if Q_min < 0 - // or: R_2 = clamp(R, L_clamp, H_clamp) - Q_min if Q_min > 0 + // that is: R_2 = clamp(R, L_clamp=0, H_clamp=Q_max) if Q_min < 0 + // or else: R_2 = clamp(R, L_clamp, H_clamp) - Q_min if Q_min >= 0 + // and also: R_2 = clamp(R, L_clamp, Q_max+1) - L_clamp if Q_min < Q_max+1 (no overflow) + // or else: R_2 = clamp(R, L_clamp, *no limit*)- L_clamp if Q_max+1 < Q_min (overflow) Node* R_2 = clamp(R, L_clamp, H_clamp); R_2 = new SubLNode(R_2, L_clamp); register_new_node(R_2, entry_control); R_2 = new ConvL2INode(R_2, TypeInt::POS); register_new_node(R_2, entry_control); - // Q = Q_min - L_clamp - // that is: Q = Q_min - 0 if Q_min < 0 - // or: Q = Q_min - Q_min = 0 if Q_min > 0 - Node* Q = new SubLNode(Q_min, L_clamp); - register_new_node(Q, entry_control); - Q = new ConvL2INode(Q, TypeInt::INT); - register_new_node(Q, entry_control); + // L_2 = Q_first - L_clamp + // We are subtracting L_clamp from both sides of the 0, then Q_first == 0 and the R.C. expression at -L_clamp and steps upward to Q_max-L_clamp. + // If S*K<0, then Q_first != 0 and the R.C. expression starts high and steps downward to Q_min-L_clamp. + Node* L_2 = new SubLNode(Q_first, L_clamp); + register_new_node(L_2, entry_control); + L_2 = new ConvL2INode(L_2, TypeInt::INT); + register_new_node(L_2, entry_control); - // Transform the range check + // Transform the range check using the computed values L_2/R_2 + // from: i*K + L (scale)); set_ctrl(K, this->C->root()); Node* scaled_iv = new MulINode(inner_phi, K); register_new_node(scaled_iv, c); - Node* scaled_iv_plus_offset = scaled_iv_plus_offset = new AddINode(scaled_iv, Q); + Node* scaled_iv_plus_offset = scaled_iv_plus_offset = new AddINode(scaled_iv, L_2); register_new_node(scaled_iv_plus_offset, c); Node* new_rc_cmp = new CmpUNode(scaled_iv_plus_offset, R_2); @@ -1621,16 +1625,6 @@ bool PhaseIdealLoop::is_counted_loop(Node* x, IdealLoopTree*&loop, BasicType iv_ return false; } - if (x->in(LoopNode::LoopBackControl)->Opcode() == Op_SafePoint && - ((iv_bt == T_INT && LoopStripMiningIter != 0) || - iv_bt == T_LONG)) { - // Leaving the safepoint on the backedge and creating a - // CountedLoop will confuse optimizations. We can't move the - // safepoint around because its jvm state wouldn't match a new - // location. Give up on that loop. - return false; - } - Node* iftrue = back_control; uint iftrue_op = iftrue->Opcode(); Node* iff = iftrue->in(0); @@ -1859,6 +1853,37 @@ bool PhaseIdealLoop::is_counted_loop(Node* x, IdealLoopTree*&loop, BasicType iv_ } } + Node* sfpt = NULL; + if (loop->_child == NULL) { + sfpt = find_safepoint(back_control, x, loop); + } else { + sfpt = iff->in(0); + if (sfpt->Opcode() != Op_SafePoint) { + sfpt = NULL; + } + } + + if (x->in(LoopNode::LoopBackControl)->Opcode() == Op_SafePoint) { + Node* backedge_sfpt = x->in(LoopNode::LoopBackControl); + if (((iv_bt == T_INT && LoopStripMiningIter != 0) || + iv_bt == T_LONG) && + sfpt == NULL) { + // Leaving the safepoint on the backedge and creating a + // CountedLoop will confuse optimizations. We can't move the + // safepoint around because its jvm state wouldn't match a new + // location. Give up on that loop. + return false; + } + if (is_deleteable_safept(backedge_sfpt)) { + lazy_replace(backedge_sfpt, iftrue); + if (loop->_safepts != NULL) { + loop->_safepts->yank(backedge_sfpt); + } + loop->_tail = iftrue; + } + } + + #ifdef ASSERT if (iv_bt == T_INT && !x->as_Loop()->is_loop_nest_inner_loop() && @@ -1897,18 +1922,6 @@ bool PhaseIdealLoop::is_counted_loop(Node* x, IdealLoopTree*&loop, BasicType iv_ } set_subtree_ctrl(adjusted_limit, false); - if (iv_bt == T_INT && LoopStripMiningIter == 0) { - // Check for SafePoint on backedge and remove - Node *sfpt = x->in(LoopNode::LoopBackControl); - if (sfpt->Opcode() == Op_SafePoint && is_deleteable_safept(sfpt)) { - lazy_replace( sfpt, iftrue ); - if (loop->_safepts != NULL) { - loop->_safepts->yank(sfpt); - } - loop->_tail = iftrue; - } - } - // Build a canonical trip test. // Clone code, as old values may be in use. incr = incr->clone(); @@ -1980,13 +1993,10 @@ bool PhaseIdealLoop::is_counted_loop(Node* x, IdealLoopTree*&loop, BasicType iv_ assert(iff->outcnt() == 0, "should be dead now"); lazy_replace( iff, le ); // fix 'get_ctrl' - Node *sfpt2 = le->in(0); - Node* entry_control = init_control; bool strip_mine_loop = iv_bt == T_INT && - LoopStripMiningIter > 1 && loop->_child == NULL && - sfpt2->Opcode() == Op_SafePoint && + sfpt != NULL && !loop->_has_call; IdealLoopTree* outer_ilt = NULL; if (strip_mine_loop) { @@ -2012,30 +2022,30 @@ bool PhaseIdealLoop::is_counted_loop(Node* x, IdealLoopTree*&loop, BasicType iv_ if (iv_bt == T_INT && (LoopStripMiningIter == 0 || strip_mine_loop)) { // Check for immediately preceding SafePoint and remove - if (sfpt2->Opcode() == Op_SafePoint && (LoopStripMiningIter != 0 || is_deleteable_safept(sfpt2))) { + if (sfpt != NULL && (strip_mine_loop || is_deleteable_safept(sfpt))) { if (strip_mine_loop) { Node* outer_le = outer_ilt->_tail->in(0); - Node* sfpt = sfpt2->clone(); - sfpt->set_req(0, iffalse); - outer_le->set_req(0, sfpt); + Node* sfpt_clone = sfpt->clone(); + sfpt_clone->set_req(0, iffalse); + outer_le->set_req(0, sfpt_clone); - Node* polladdr = sfpt->in(TypeFunc::Parms); + Node* polladdr = sfpt_clone->in(TypeFunc::Parms); if (polladdr != nullptr && polladdr->is_Load()) { // Polling load should be pinned outside inner loop. Node* new_polladdr = polladdr->clone(); new_polladdr->set_req(0, iffalse); _igvn.register_new_node_with_optimizer(new_polladdr, polladdr); set_ctrl(new_polladdr, iffalse); - sfpt->set_req(TypeFunc::Parms, new_polladdr); + sfpt_clone->set_req(TypeFunc::Parms, new_polladdr); } // When this code runs, loop bodies have not yet been populated. const bool body_populated = false; - register_control(sfpt, outer_ilt, iffalse, body_populated); - set_idom(outer_le, sfpt, dom_depth(sfpt)); + register_control(sfpt_clone, outer_ilt, iffalse, body_populated); + set_idom(outer_le, sfpt_clone, dom_depth(sfpt_clone)); } - lazy_replace( sfpt2, sfpt2->in(TypeFunc::Control)); + lazy_replace(sfpt, sfpt->in(TypeFunc::Control)); if (loop->_safepts != NULL) { - loop->_safepts->yank(sfpt2); + loop->_safepts->yank(sfpt); } } } @@ -2554,6 +2564,123 @@ BaseCountedLoopNode* BaseCountedLoopNode::make(Node* entry, Node* backedge, Basi return new LongCountedLoopNode(entry, backedge); } +void OuterStripMinedLoopNode::fix_sunk_stores(CountedLoopEndNode* inner_cle, LoopNode* inner_cl, PhaseIterGVN* igvn, + PhaseIdealLoop* iloop) { + Node* cle_out = inner_cle->proj_out(false); + Node* cle_tail = inner_cle->proj_out(true); + if (cle_out->outcnt() > 1) { + // Look for chains of stores that were sunk + // out of the inner loop and are in the outer loop + for (DUIterator_Fast imax, i = cle_out->fast_outs(imax); i < imax; i++) { + Node* u = cle_out->fast_out(i); + if (u->is_Store()) { + int alias_idx = igvn->C->get_alias_index(u->adr_type()); + Node* first = u; + for (;;) { + Node* next = first->in(MemNode::Memory); + if (!next->is_Store() || next->in(0) != cle_out) { + break; + } + assert(igvn->C->get_alias_index(next->adr_type()) == alias_idx, ""); + first = next; + } + Node* last = u; + for (;;) { + Node* next = NULL; + for (DUIterator_Fast jmax, j = last->fast_outs(jmax); j < jmax; j++) { + Node* uu = last->fast_out(j); + if (uu->is_Store() && uu->in(0) == cle_out) { + assert(next == NULL, "only one in the outer loop"); + next = uu; + assert(igvn->C->get_alias_index(next->adr_type()) == alias_idx, ""); + } + } + if (next == NULL) { + break; + } + last = next; + } + Node* phi = NULL; + for (DUIterator_Fast jmax, j = inner_cl->fast_outs(jmax); j < jmax; j++) { + Node* uu = inner_cl->fast_out(j); + if (uu->is_Phi()) { + Node* be = uu->in(LoopNode::LoopBackControl); + if (be->is_Store() && be->in(0) == inner_cl->in(LoopNode::LoopBackControl)) { + assert(igvn->C->get_alias_index(uu->adr_type()) != alias_idx && igvn->C->get_alias_index(uu->adr_type()) != Compile::AliasIdxBot, "unexpected store"); + } + if (be == last || be == first->in(MemNode::Memory)) { + assert(igvn->C->get_alias_index(uu->adr_type()) == alias_idx || igvn->C->get_alias_index(uu->adr_type()) == Compile::AliasIdxBot, "unexpected alias"); + assert(phi == NULL, "only one phi"); + phi = uu; + } + } + } +#ifdef ASSERT + for (DUIterator_Fast jmax, j = inner_cl->fast_outs(jmax); j < jmax; j++) { + Node* uu = inner_cl->fast_out(j); + if (uu->is_Phi() && uu->bottom_type() == Type::MEMORY) { + if (uu->adr_type() == igvn->C->get_adr_type(igvn->C->get_alias_index(u->adr_type()))) { + assert(phi == uu, "what's that phi?"); + } else if (uu->adr_type() == TypePtr::BOTTOM) { + Node* n = uu->in(LoopNode::LoopBackControl); + uint limit = igvn->C->live_nodes(); + uint i = 0; + while (n != uu) { + i++; + assert(i < limit, "infinite loop"); + if (n->is_Proj()) { + n = n->in(0); + } else if (n->is_SafePoint() || n->is_MemBar()) { + n = n->in(TypeFunc::Memory); + } else if (n->is_Phi()) { + n = n->in(1); + } else if (n->is_MergeMem()) { + n = n->as_MergeMem()->memory_at(igvn->C->get_alias_index(u->adr_type())); + } else if (n->is_Store() || n->is_LoadStore() || n->is_ClearArray()) { + n = n->in(MemNode::Memory); + } else { + n->dump(); + ShouldNotReachHere(); + } + } + } + } + } +#endif + if (phi == NULL) { + // If an entire chains was sunk, the + // inner loop has no phi for that memory + // slice, create one for the outer loop + phi = PhiNode::make(inner_cl, first->in(MemNode::Memory), Type::MEMORY, + igvn->C->get_adr_type(igvn->C->get_alias_index(u->adr_type()))); + phi->set_req(LoopNode::LoopBackControl, last); + phi = register_new_node(phi, inner_cl, igvn, iloop); + igvn->replace_input_of(first, MemNode::Memory, phi); + } else { + // Or fix the outer loop fix to include + // that chain of stores. + Node* be = phi->in(LoopNode::LoopBackControl); + assert(!(be->is_Store() && be->in(0) == inner_cl->in(LoopNode::LoopBackControl)), "store on the backedge + sunk stores: unsupported"); + if (be == first->in(MemNode::Memory)) { + if (be == phi->in(LoopNode::LoopBackControl)) { + igvn->replace_input_of(phi, LoopNode::LoopBackControl, last); + } else { + igvn->replace_input_of(be, MemNode::Memory, last); + } + } else { +#ifdef ASSERT + if (be == phi->in(LoopNode::LoopBackControl)) { + assert(phi->in(LoopNode::LoopBackControl) == last, ""); + } else { + assert(be->in(MemNode::Memory) == last, ""); + } +#endif + } + } + } + } + } +} void OuterStripMinedLoopNode::adjust_strip_mined_loop(PhaseIterGVN* igvn) { // Look for the outer & inner strip mined loop, reduce number of @@ -2561,6 +2688,14 @@ void OuterStripMinedLoopNode::adjust_strip_mined_loop(PhaseIterGVN* igvn) { // construct required phi nodes for outer loop. CountedLoopNode* inner_cl = unique_ctrl_out()->as_CountedLoop(); assert(inner_cl->is_strip_mined(), "inner loop should be strip mined"); + if (LoopStripMiningIter == 0) { + remove_outer_loop_and_safepoint(igvn); + return; + } + if (LoopStripMiningIter == 1) { + transform_to_counted_loop(igvn, NULL); + return; + } Node* inner_iv_phi = inner_cl->phi(); if (inner_iv_phi == NULL) { IfNode* outer_le = outer_loop_end(); @@ -2580,11 +2715,7 @@ void OuterStripMinedLoopNode::adjust_strip_mined_loop(PhaseIterGVN* igvn) { assert(iter_estimate > 0, "broken"); if ((jlong)scaled_iters != scaled_iters_long || iter_estimate <= short_scaled_iters) { // Remove outer loop and safepoint (too few iterations) - Node* outer_sfpt = outer_safepoint(); - Node* outer_out = outer_loop_exit(); - igvn->replace_node(outer_out, outer_sfpt->in(0)); - igvn->replace_input_of(outer_sfpt, 0, igvn->C->top()); - inner_cl->clear_strip_mined(); + remove_outer_loop_and_safepoint(igvn); return; } if (iter_estimate <= scaled_iters_long) { @@ -2665,121 +2796,6 @@ void OuterStripMinedLoopNode::adjust_strip_mined_loop(PhaseIterGVN* igvn) { } } } - Node* cle_out = inner_cle->proj_out(false); - if (cle_out->outcnt() > 1) { - // Look for chains of stores that were sunk - // out of the inner loop and are in the outer loop - for (DUIterator_Fast imax, i = cle_out->fast_outs(imax); i < imax; i++) { - Node* u = cle_out->fast_out(i); - if (u->is_Store()) { - Node* first = u; - for(;;) { - Node* next = first->in(MemNode::Memory); - if (!next->is_Store() || next->in(0) != cle_out) { - break; - } - first = next; - } - Node* last = u; - for(;;) { - Node* next = NULL; - for (DUIterator_Fast jmax, j = last->fast_outs(jmax); j < jmax; j++) { - Node* uu = last->fast_out(j); - if (uu->is_Store() && uu->in(0) == cle_out) { - assert(next == NULL, "only one in the outer loop"); - next = uu; - } - } - if (next == NULL) { - break; - } - last = next; - } - Node* phi = NULL; - for (DUIterator_Fast jmax, j = fast_outs(jmax); j < jmax; j++) { - Node* uu = fast_out(j); - if (uu->is_Phi()) { - Node* be = uu->in(LoopNode::LoopBackControl); - if (be->is_Store() && old_new[be->_idx] != NULL) { - assert(false, "store on the backedge + sunk stores: unsupported"); - // drop outer loop - IfNode* outer_le = outer_loop_end(); - Node* iff = igvn->transform(new IfNode(outer_le->in(0), outer_le->in(1), outer_le->_prob, outer_le->_fcnt)); - igvn->replace_node(outer_le, iff); - inner_cl->clear_strip_mined(); - return; - } - if (be == last || be == first->in(MemNode::Memory)) { - assert(phi == NULL, "only one phi"); - phi = uu; - } - } - } -#ifdef ASSERT - for (DUIterator_Fast jmax, j = fast_outs(jmax); j < jmax; j++) { - Node* uu = fast_out(j); - if (uu->is_Phi() && uu->bottom_type() == Type::MEMORY) { - if (uu->adr_type() == igvn->C->get_adr_type(igvn->C->get_alias_index(u->adr_type()))) { - assert(phi == uu, "what's that phi?"); - } else if (uu->adr_type() == TypePtr::BOTTOM) { - Node* n = uu->in(LoopNode::LoopBackControl); - uint limit = igvn->C->live_nodes(); - uint i = 0; - while (n != uu) { - i++; - assert(i < limit, "infinite loop"); - if (n->is_Proj()) { - n = n->in(0); - } else if (n->is_SafePoint() || n->is_MemBar()) { - n = n->in(TypeFunc::Memory); - } else if (n->is_Phi()) { - n = n->in(1); - } else if (n->is_MergeMem()) { - n = n->as_MergeMem()->memory_at(igvn->C->get_alias_index(u->adr_type())); - } else if (n->is_Store() || n->is_LoadStore() || n->is_ClearArray()) { - n = n->in(MemNode::Memory); - } else { - n->dump(); - ShouldNotReachHere(); - } - } - } - } - } -#endif - if (phi == NULL) { - // If the an entire chains was sunk, the - // inner loop has no phi for that memory - // slice, create one for the outer loop - phi = PhiNode::make(this, first->in(MemNode::Memory), Type::MEMORY, - igvn->C->get_adr_type(igvn->C->get_alias_index(u->adr_type()))); - phi->set_req(LoopNode::LoopBackControl, last); - phi = igvn->transform(phi); - igvn->replace_input_of(first, MemNode::Memory, phi); - } else { - // Or fix the outer loop fix to include - // that chain of stores. - Node* be = phi->in(LoopNode::LoopBackControl); - assert(!(be->is_Store() && old_new[be->_idx] != NULL), "store on the backedge + sunk stores: unsupported"); - if (be == first->in(MemNode::Memory)) { - if (be == phi->in(LoopNode::LoopBackControl)) { - igvn->replace_input_of(phi, LoopNode::LoopBackControl, last); - } else { - igvn->replace_input_of(be, MemNode::Memory, last); - } - } else { -#ifdef ASSERT - if (be == phi->in(LoopNode::LoopBackControl)) { - assert(phi->in(LoopNode::LoopBackControl) == last, ""); - } else { - assert(be->in(MemNode::Memory) == last, ""); - } -#endif - } - } - } - } - } if (iv_phi != NULL) { // Now adjust the inner loop's exit condition @@ -2828,6 +2844,96 @@ void OuterStripMinedLoopNode::adjust_strip_mined_loop(PhaseIterGVN* igvn) { } } +void OuterStripMinedLoopNode::transform_to_counted_loop(PhaseIterGVN* igvn, PhaseIdealLoop* iloop) { + CountedLoopNode* inner_cl = unique_ctrl_out()->as_CountedLoop(); + CountedLoopEndNode* cle = inner_cl->loopexit(); + Node* inner_test = cle->in(1); + IfNode* outer_le = outer_loop_end(); + CountedLoopEndNode* inner_cle = inner_cl->loopexit(); + Node* safepoint = outer_safepoint(); + + fix_sunk_stores(inner_cle, inner_cl, igvn, iloop); + + // make counted loop exit test always fail + ConINode* zero = igvn->intcon(0); + if (iloop != NULL) { + iloop->set_ctrl(zero, igvn->C->root()); + } + igvn->replace_input_of(cle, 1, zero); + // replace outer loop end with CountedLoopEndNode with formers' CLE's exit test + Node* new_end = new CountedLoopEndNode(outer_le->in(0), inner_test, cle->_prob, cle->_fcnt); + register_control(new_end, inner_cl, outer_le->in(0), igvn, iloop); + if (iloop == NULL) { + igvn->replace_node(outer_le, new_end); + } else { + iloop->lazy_replace(outer_le, new_end); + } + // the backedge of the inner loop must be rewired to the new loop end + Node* backedge = cle->proj_out(true); + igvn->replace_input_of(backedge, 0, new_end); + if (iloop != NULL) { + iloop->set_idom(backedge, new_end, iloop->dom_depth(new_end) + 1); + } + // make the outer loop go away + igvn->replace_input_of(in(LoopBackControl), 0, igvn->C->top()); + igvn->replace_input_of(this, LoopBackControl, igvn->C->top()); + inner_cl->clear_strip_mined(); + if (iloop != NULL) { + Unique_Node_List wq; + wq.push(safepoint); + + IdealLoopTree* outer_loop_ilt = iloop->get_loop(this); + IdealLoopTree* loop = iloop->get_loop(inner_cl); + + for (uint i = 0; i < wq.size(); i++) { + Node* n = wq.at(i); + for (uint j = 0; j < n->req(); ++j) { + Node* in = n->in(j); + if (in == NULL || in->is_CFG()) { + continue; + } + if (iloop->get_loop(iloop->get_ctrl(in)) != outer_loop_ilt) { + continue; + } + assert(!loop->_body.contains(in), ""); + loop->_body.push(in); + wq.push(in); + } + } + iloop->set_loop(safepoint, loop); + loop->_body.push(safepoint); + iloop->set_loop(safepoint->in(0), loop); + loop->_body.push(safepoint->in(0)); + outer_loop_ilt->_tail = igvn->C->top(); + } +} + +void OuterStripMinedLoopNode::remove_outer_loop_and_safepoint(PhaseIterGVN* igvn) const { + CountedLoopNode* inner_cl = unique_ctrl_out()->as_CountedLoop(); + Node* outer_sfpt = outer_safepoint(); + Node* outer_out = outer_loop_exit(); + igvn->replace_node(outer_out, outer_sfpt->in(0)); + igvn->replace_input_of(outer_sfpt, 0, igvn->C->top()); + inner_cl->clear_strip_mined(); +} + +Node* OuterStripMinedLoopNode::register_new_node(Node* node, LoopNode* ctrl, PhaseIterGVN* igvn, PhaseIdealLoop* iloop) { + if (iloop == NULL) { + return igvn->transform(node); + } + iloop->register_new_node(node, ctrl); + return node; +} + +Node* OuterStripMinedLoopNode::register_control(Node* node, Node* loop, Node* idom, PhaseIterGVN* igvn, + PhaseIdealLoop* iloop) { + if (iloop == NULL) { + return igvn->transform(node); + } + iloop->register_control(node, iloop->get_loop(loop), idom); + return node; +} + const Type* OuterStripMinedLoopEndNode::Value(PhaseGVN* phase) const { if (!in(0)) return Type::TOP; if (phase->type(in(0)) == Type::TOP) @@ -3663,7 +3769,7 @@ void IdealLoopTree::counted_loop( PhaseIdealLoop *phase ) { if (_head->is_CountedLoop() || phase->is_counted_loop(_head, loop, T_INT)) { - if (LoopStripMiningIter == 0 || (LoopStripMiningIter > 1 && _child == NULL)) { + if (LoopStripMiningIter == 0 || _head->as_CountedLoop()->is_strip_mined()) { // Indicate we do not need a safepoint here _has_sfpt = 1; } @@ -4089,11 +4195,11 @@ bool PhaseIdealLoop::only_has_infinite_loops() { //----------------------------build_and_optimize------------------------------- // Create a PhaseLoop. Build the ideal Loop tree. Map each Ideal Node to // its corresponding LoopNode. If 'optimize' is true, do some loop cleanups. -void PhaseIdealLoop::build_and_optimize(LoopOptsMode mode) { +void PhaseIdealLoop::build_and_optimize() { assert(!C->post_loop_opts_phase(), "no loop opts allowed"); - bool do_split_ifs = (mode == LoopOptsDefault); - bool skip_loop_opts = (mode == LoopOptsNone); + bool do_split_ifs = (_mode == LoopOptsDefault); + bool skip_loop_opts = (_mode == LoopOptsNone); int old_progress = C->major_progress(); uint orig_worklist_size = _igvn._worklist.size(); @@ -4164,9 +4270,9 @@ void PhaseIdealLoop::build_and_optimize(LoopOptsMode mode) { BarrierSetC2* bs = BarrierSet::barrier_set()->barrier_set_c2(); // Nothing to do, so get out bool stop_early = !C->has_loops() && !skip_loop_opts && !do_split_ifs && !_verify_me && !_verify_only && - !bs->is_gc_specific_loop_opts_pass(mode); + !bs->is_gc_specific_loop_opts_pass(_mode); bool do_expensive_nodes = C->should_optimize_expensive_nodes(_igvn); - bool strip_mined_loops_expanded = bs->strip_mined_loops_expanded(mode); + bool strip_mined_loops_expanded = bs->strip_mined_loops_expanded(_mode); if (stop_early && !do_expensive_nodes) { return; } @@ -4258,7 +4364,7 @@ void PhaseIdealLoop::build_and_optimize(LoopOptsMode mode) { if (_verify_only) { C->restore_major_progress(old_progress); - assert(C->unique() == unique, "verification mode made Nodes? ? ?"); + assert(C->unique() == unique, "verification _mode made Nodes? ? ?"); assert(_igvn._worklist.size() == orig_worklist_size, "shouldn't push anything"); return; } @@ -4288,8 +4394,8 @@ void PhaseIdealLoop::build_and_optimize(LoopOptsMode mode) { #ifndef PRODUCT C->verify_graph_edges(); if (_verify_me) { // Nested verify pass? - // Check to see if the verify mode is broken - assert(C->unique() == unique, "non-optimize mode made Nodes? ? ?"); + // Check to see if the verify _mode is broken + assert(C->unique() == unique, "non-optimize _mode made Nodes? ? ?"); return; } if (VerifyLoopOptimizations) verify(); @@ -4303,7 +4409,7 @@ void PhaseIdealLoop::build_and_optimize(LoopOptsMode mode) { return; } - if (mode == LoopOptsMaxUnroll) { + if (_mode == LoopOptsMaxUnroll) { for (LoopTreeIterator iter(_ltree_root); !iter.done(); iter.next()) { IdealLoopTree* lpt = iter.current(); if (lpt->is_innermost() && lpt->_allow_optimizations && !lpt->_has_call && lpt->is_counted()) { @@ -4324,7 +4430,7 @@ void PhaseIdealLoop::build_and_optimize(LoopOptsMode mode) { return; } - if (bs->optimize_loops(this, mode, visited, nstack, worklist)) { + if (bs->optimize_loops(this, _mode, visited, nstack, worklist)) { return; } @@ -5669,7 +5775,7 @@ void PhaseIdealLoop::build_loop_late_post_work(Node *n, bool pinned) { case Op_StrIndexOf: case Op_StrIndexOfChar: case Op_AryEq: - case Op_HasNegatives: + case Op_CountPositives: pinned = false; } if (n->is_CMove() || n->is_ConstraintCast()) { @@ -5755,7 +5861,7 @@ void PhaseIdealLoop::build_loop_late_post_work(Node *n, bool pinned) { } // Try not to place code on a loop entry projection // which can inhibit range check elimination. - if (least != early) { + if (least != early && !BarrierSet::barrier_set()->barrier_set_c2()->is_gc_specific_loop_opts_pass(_mode)) { Node* ctrl_out = least->unique_ctrl_out_or_null(); if (ctrl_out != NULL && ctrl_out->is_Loop() && least == ctrl_out->in(LoopNode::EntryControl) && diff --git a/src/hotspot/share/opto/loopnode.hpp b/src/hotspot/share/opto/loopnode.hpp index f3eaabebae10222d366871769200c65d8b2c5d8e..c81180fa7b82d7797aa23cc35d77a81a1e925afa 100644 --- a/src/hotspot/share/opto/loopnode.hpp +++ b/src/hotspot/share/opto/loopnode.hpp @@ -546,7 +546,8 @@ class LoopLimitNode : public Node { // Support for strip mining class OuterStripMinedLoopNode : public LoopNode { private: - CountedLoopNode* inner_loop() const; + static void fix_sunk_stores(CountedLoopEndNode* inner_cle, LoopNode* inner_cl, PhaseIterGVN* igvn, PhaseIdealLoop* iloop); + public: OuterStripMinedLoopNode(Compile* C, Node *entry, Node *backedge) : LoopNode(entry, backedge) { @@ -562,6 +563,15 @@ public: virtual IfFalseNode* outer_loop_exit() const; virtual SafePointNode* outer_safepoint() const; void adjust_strip_mined_loop(PhaseIterGVN* igvn); + + void remove_outer_loop_and_safepoint(PhaseIterGVN* igvn) const; + + void transform_to_counted_loop(PhaseIterGVN* igvn, PhaseIdealLoop* iloop); + + static Node* register_new_node(Node* node, LoopNode* ctrl, PhaseIterGVN* igvn, PhaseIdealLoop* iloop); + + Node* register_control(Node* node, Node* loop, Node* idom, PhaseIterGVN* igvn, + PhaseIdealLoop* iloop); }; class OuterStripMinedLoopEndNode : public IfNode { @@ -1042,9 +1052,10 @@ private: Node **_idom; // Array of immediate dominators uint *_dom_depth; // Used for fast LCA test GrowableArray* _dom_stk; // For recomputation of dom depth + LoopOptsMode _mode; // build the loop tree and perform any requested optimizations - void build_and_optimize(LoopOptsMode mode); + void build_and_optimize(); // Dominators for the sea of nodes void Dominators(); @@ -1055,9 +1066,10 @@ private: _igvn(igvn), _verify_me(nullptr), _verify_only(false), + _mode(mode), _nodes_required(UINT_MAX) { assert(mode != LoopOptsVerify, "wrong constructor to verify IdealLoop"); - build_and_optimize(mode); + build_and_optimize(); } #ifndef PRODUCT @@ -1068,8 +1080,9 @@ private: _igvn(igvn), _verify_me(verify_me), _verify_only(verify_me == nullptr), + _mode(LoopOptsVerify), _nodes_required(UINT_MAX) { - build_and_optimize(LoopOptsVerify); + build_and_optimize(); } #endif @@ -1262,15 +1275,15 @@ public: void mark_reductions( IdealLoopTree *loop ); // Return true if exp is a constant times an induction var - bool is_scaled_iv(Node* exp, Node* iv, jlong* p_scale, BasicType bt, bool* converted); + bool is_scaled_iv(Node* exp, Node* iv, BasicType bt, jlong* p_scale, bool* p_short_scale, int depth = 0); bool is_iv(Node* exp, Node* iv, BasicType bt); // Return true if exp is a scaled induction var plus (or minus) constant - bool is_scaled_iv_plus_offset(Node* exp, Node* iv, jlong* p_scale, Node** p_offset, BasicType bt, bool* converted = NULL, int depth = 0); + bool is_scaled_iv_plus_offset(Node* exp, Node* iv, BasicType bt, jlong* p_scale, Node** p_offset, bool* p_short_scale = NULL, int depth = 0); bool is_scaled_iv_plus_offset(Node* exp, Node* iv, int* p_scale, Node** p_offset) { jlong long_scale; - if (is_scaled_iv_plus_offset(exp, iv, &long_scale, p_offset, T_INT)) { + if (is_scaled_iv_plus_offset(exp, iv, T_INT, &long_scale, p_offset)) { int int_scale = checked_cast(long_scale); if (p_scale != NULL) { *p_scale = int_scale; @@ -1279,6 +1292,12 @@ public: } return false; } + // Helper for finding more complex matches to is_scaled_iv_plus_offset. + bool is_scaled_iv_plus_extra_offset(Node* exp1, Node* offset2, Node* iv, + BasicType bt, + jlong* p_scale, Node** p_offset, + bool* p_short_scale, int depth); + // Enum to determine the action to be performed in create_new_if_for_predicate() when processing phis of UCT regions. enum class UnswitchingAction { @@ -1653,8 +1672,6 @@ public: bool safe_for_if_replacement(const Node* dom) const; - void strip_mined_nest_back_to_counted_loop(IdealLoopTree* loop, const BaseCountedLoopNode* head, Node* back_control, - IfNode*&exit_test, SafePointNode*&safepoint); void push_pinned_nodes_thru_region(IfNode* dom_if, Node* region); bool try_merge_identical_ifs(Node* n); diff --git a/src/hotspot/share/opto/loopopts.cpp b/src/hotspot/share/opto/loopopts.cpp index a7c82ad2ee15de8efaf9922b0ce6c2a4e02cab35..dc9cddfdabf708fd85325528562c54878bd44f9a 100644 --- a/src/hotspot/share/opto/loopopts.cpp +++ b/src/hotspot/share/opto/loopopts.cpp @@ -3828,6 +3828,8 @@ void PhaseIdealLoop::reorg_offsets(IdealLoopTree *loop) { set_ctrl(neg_stride, C->root()); Node *post = new AddINode(opaq, neg_stride); register_new_node(post, c); + post = new CastIINode(post, phi->bottom_type()); // preserve the iv phi's type + register_new_node(post, c); _igvn.rehash_node_delayed(use); for (uint j = 1; j < use->req(); j++) { if (use->in(j) == phi) diff --git a/src/hotspot/share/opto/machnode.hpp b/src/hotspot/share/opto/machnode.hpp index ea24b4059ac99d01fdff418d5c73f57d6e1dfe46..3c155f6448a184017caafbfd7042d13b14f04d10 100644 --- a/src/hotspot/share/opto/machnode.hpp +++ b/src/hotspot/share/opto/machnode.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -204,9 +204,6 @@ public: // Base type for all machine specific nodes. All node classes generated by the // ADLC inherit from this class. class MachNode : public Node { -private: - bool _removed = false; - public: MachNode() : Node((uint)0), _barrier(0), _num_opnds(0), _opnds(NULL) { init_class_id(Class_Mach); @@ -277,9 +274,9 @@ public: // more leafs. Must be set by MachNode constructor to point to an // internal array of MachOpers. The MachOper array is sized by // specific MachNodes described in the ADL. - uint _num_opnds; + uint16_t _num_opnds; MachOper **_opnds; - uint num_opnds() const { return _num_opnds; } + uint16_t num_opnds() const { return _num_opnds; } // Emit bytes into cbuf virtual void emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const; @@ -375,8 +372,8 @@ public: // Returns true if this node is a check that can be implemented with a trap. virtual bool is_TrapBasedCheckNode() const { return false; } - void set_removed() { _removed = true; } - bool get_removed() { return _removed; } + void set_removed() { add_flag(Flag_is_removed_by_peephole); } + bool get_removed() { return (flags() & Flag_is_removed_by_peephole) != 0; } #ifndef PRODUCT virtual const char *Name() const = 0; // Machine-specific name diff --git a/src/hotspot/share/opto/matcher.cpp b/src/hotspot/share/opto/matcher.cpp index 35ccf26e7cb82ea01eaf2888d1a2de820eb42f14..20a08e0cb4ba05bb8a8cc5dcd6ae28ee463ee285 100644 --- a/src/hotspot/share/opto/matcher.cpp +++ b/src/hotspot/share/opto/matcher.cpp @@ -1066,7 +1066,7 @@ static void match_alias_type(Compile* C, Node* n, Node* m) { case Op_StrIndexOf: case Op_StrIndexOfChar: case Op_AryEq: - case Op_HasNegatives: + case Op_CountPositives: case Op_MemBarVolatile: case Op_MemBarCPUOrder: // %%% these ideals should have narrower adr_type? case Op_StrInflatedCopy: @@ -2252,7 +2252,7 @@ bool Matcher::find_shared_visit(MStack& mstack, Node* n, uint opcode, bool& mem_ case Op_StrIndexOf: case Op_StrIndexOfChar: case Op_AryEq: - case Op_HasNegatives: + case Op_CountPositives: case Op_StrInflatedCopy: case Op_StrCompressedCopy: case Op_EncodeISOArray: diff --git a/src/hotspot/share/opto/node.hpp b/src/hotspot/share/opto/node.hpp index d8bf863a9864d97e2ccb780463d08419357f4076..748db2867100f73b0f3461042378f3fc0510287c 100644 --- a/src/hotspot/share/opto/node.hpp +++ b/src/hotspot/share/opto/node.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -786,7 +786,8 @@ public: Flag_is_expensive = 1 << 14, Flag_is_predicated_vector = 1 << 15, Flag_for_post_loop_opts_igvn = 1 << 16, - _last_flag = Flag_for_post_loop_opts_igvn + Flag_is_removed_by_peephole = 1 << 17, + _last_flag = Flag_is_removed_by_peephole }; class PD; @@ -1152,7 +1153,12 @@ public: jlong get_integer_as_long(BasicType bt) const { const TypeInteger* t = find_integer_type(bt); - guarantee(t != NULL, "must be con"); + guarantee(t != NULL && t->is_con(), "must be con"); + return t->get_con_as_long(bt); + } + jlong find_integer_as_long(BasicType bt, jlong value_if_unknown) const { + const TypeInteger* t = find_integer_type(bt); + if (t == NULL || !t->is_con()) return value_if_unknown; return t->get_con_as_long(bt); } const TypePtr* get_ptr_type() const; @@ -1247,15 +1253,16 @@ public: #ifdef ASSERT void verify_construction(); bool verify_jvms(const JVMState* jvms) const; - int _debug_idx; // Unique value assigned to every node. - int debug_idx() const { return _debug_idx; } - void set_debug_idx( int debug_idx ) { _debug_idx = debug_idx; } Node* _debug_orig; // Original version of this, if any. Node* debug_orig() const { return _debug_orig; } void set_debug_orig(Node* orig); // _debug_orig = orig void dump_orig(outputStream *st, bool print_key = true) const; + int _debug_idx; // Unique value assigned to every node. + int debug_idx() const { return _debug_idx; } + void set_debug_idx( int debug_idx ) { _debug_idx = debug_idx; } + int _hash_lock; // Barrier to modifications of nodes in the hash table void enter_hash_lock() { ++_hash_lock; assert(_hash_lock < 99, "in too many hash tables?"); } void exit_hash_lock() { --_hash_lock; assert(_hash_lock >= 0, "mispaired hash locks"); } diff --git a/src/hotspot/share/opto/phaseX.cpp b/src/hotspot/share/opto/phaseX.cpp index 0589d1eab0c96bf8aa1f540fdea485ec2ce47c5a..9df9a18dbf7cc2aa96683b5765b1a08489175c67 100644 --- a/src/hotspot/share/opto/phaseX.cpp +++ b/src/hotspot/share/opto/phaseX.cpp @@ -1691,7 +1691,7 @@ bool PhaseIterGVN::no_dependent_zero_check(Node* n) const { case Op_DivI: case Op_ModI: { // Type of divisor includes 0? - if (n->in(2)->is_top()) { + if (type(n->in(2)) == Type::TOP) { // 'n' is dead. Treat as if zero check is still there to avoid any further optimizations. return false; } @@ -1701,7 +1701,7 @@ bool PhaseIterGVN::no_dependent_zero_check(Node* n) const { case Op_DivL: case Op_ModL: { // Type of divisor includes 0? - if (n->in(2)->is_top()) { + if (type(n->in(2)) == Type::TOP) { // 'n' is dead. Treat as if zero check is still there to avoid any further optimizations. return false; } diff --git a/src/hotspot/share/opto/runtime.cpp b/src/hotspot/share/opto/runtime.cpp index c2df7b3b2a13d4d21143542c0a5cb10ab34f079f..c20b55a1b339130acfef36baa23f34cc38691d31 100644 --- a/src/hotspot/share/opto/runtime.cpp +++ b/src/hotspot/share/opto/runtime.cpp @@ -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 @@ -1465,6 +1465,12 @@ address OptoRuntime::rethrow_C(oopDesc* exception, JavaThread* thread, address r // Enable WXWrite: the function called directly by compiled code. MACOS_AARCH64_ONLY(ThreadWXEnable wx(WXWrite, thread)); + // ret_pc will have been loaded from the stack, so for AArch64 will be signed. + // This needs authenticating, but to do that here requires the fp of the previous frame. + // A better way of doing it would be authenticate in the caller by adding a + // AuthPAuthNode and using it in GraphKit::gen_stub. For now, just strip it. + AARCH64_PORT_ONLY(ret_pc = pauth_strip_pointer(ret_pc)); + #ifndef PRODUCT SharedRuntime::_rethrow_ctr++; // count rethrows #endif diff --git a/src/hotspot/share/opto/subnode.cpp b/src/hotspot/share/opto/subnode.cpp index 67b60f74c6098004f12e03ac1f7686122e2ec5f5..7897a2e99d39e6f22765debbdf1aa4fa0ab40231 100644 --- a/src/hotspot/share/opto/subnode.cpp +++ b/src/hotspot/share/opto/subnode.cpp @@ -61,7 +61,7 @@ Node* SubNode::Identity(PhaseGVN* phase) { } // Convert "(X+Y) - Y" into X and "(X+Y) - X" into Y - if (in(1)->Opcode() == Op_AddI) { + if (in(1)->Opcode() == Op_AddI || in(1)->Opcode() == Op_AddL) { if (in(1)->in(2) == in(2)) { return in(1)->in(1); } @@ -417,6 +417,10 @@ Node *SubLNode::Ideal(PhaseGVN *phase, bool can_reshape) { if (op2 == Op_AddL && in1 == in2->in(1)) { return new SubLNode(phase->makecon(TypeLong::ZERO), in2->in(2)); } + // Convert "(x-y) - x" into "-y" + if (op1 == Op_SubL && in1->in(1) == in2) { + return new SubLNode(phase->makecon(TypeLong::ZERO), in1->in(2)); + } // Convert "x - (y+x)" into "-y" if (op2 == Op_AddL && in1 == in2->in(2)) { return new SubLNode(phase->makecon(TypeLong::ZERO), in2->in(1)); diff --git a/src/hotspot/share/opto/subtypenode.cpp b/src/hotspot/share/opto/subtypenode.cpp index 10604cfebcc5f83ebb4423e5c6b9c39db2ea4f0f..c90b74b7d22c734d0298e9b8018ace7c26336c90 100644 --- a/src/hotspot/share/opto/subtypenode.cpp +++ b/src/hotspot/share/opto/subtypenode.cpp @@ -135,7 +135,7 @@ Node *SubTypeCheckNode::Ideal(PhaseGVN* phase, bool can_reshape) { Node* obj = AddPNode::Ideal_base_and_offset(addr, phase, con); if (con == oopDesc::klass_offset_in_bytes() && obj != NULL) { assert(is_oop(phase, obj), "only for oop input"); - set_req(ObjOrSubKlass, obj); + set_req_X(ObjOrSubKlass, obj, phase); return this; } } @@ -144,7 +144,7 @@ Node *SubTypeCheckNode::Ideal(PhaseGVN* phase, bool can_reshape) { Node* allocated_klass = AllocateNode::Ideal_klass(obj_or_subklass, phase); if (allocated_klass != NULL) { assert(is_oop(phase, obj_or_subklass), "only for oop input"); - set_req(ObjOrSubKlass, allocated_klass); + set_req_X(ObjOrSubKlass, allocated_klass, phase); return this; } diff --git a/src/hotspot/share/prims/forte.cpp b/src/hotspot/share/prims/forte.cpp index c68c371ce47989388e90e2ce5754d326c8ab6f19..ce9b30b17c05d6383e263bd011adc45bb492cb88 100644 --- a/src/hotspot/share/prims/forte.cpp +++ b/src/hotspot/share/prims/forte.cpp @@ -562,12 +562,11 @@ static void forte_fill_call_trace_given_top(JavaThread* thd, extern "C" { JNIEXPORT void AsyncGetCallTrace(ASGCT_CallTrace *trace, jint depth, void* ucontext) { + JavaThread* thread; if (trace->env_id == NULL || - (thread = JavaThread::thread_from_jni_environment(trace->env_id)) == NULL || - thread->is_exiting()) { - + (thread = JavaThread::thread_from_jni_environment(trace->env_id))->is_exiting()) { // bad env_id, thread has exited or thread is exiting trace->num_frames = ticks_thread_exit; // -8 return; diff --git a/src/hotspot/share/prims/jvm.cpp b/src/hotspot/share/prims/jvm.cpp index d8a5a025b9d85058747807ba764d07bd429f26a5..c574cb3ecc8c07571b4f3f44414b519aad3d4089 100644 --- a/src/hotspot/share/prims/jvm.cpp +++ b/src/hotspot/share/prims/jvm.cpp @@ -487,7 +487,7 @@ JVM_ENTRY_NO_ENV(jint, JVM_ActiveProcessorCount(void)) return os::active_processor_count(); JVM_END -JVM_ENTRY_NO_ENV(jboolean, JVM_IsUseContainerSupport(void)) +JVM_LEAF(jboolean, JVM_IsUseContainerSupport(void)) #ifdef LINUX if (UseContainerSupport) { return JNI_TRUE; @@ -690,7 +690,7 @@ JVM_ENTRY(void, JVM_ReportFinalizationComplete(JNIEnv * env, jobject finalizee)) MANAGEMENT_ONLY(FinalizerService::on_complete(JNIHandles::resolve_non_null(finalizee), THREAD);) JVM_END -JVM_ENTRY(jboolean, JVM_IsFinalizationEnabled(JNIEnv * env)) +JVM_LEAF(jboolean, JVM_IsFinalizationEnabled(JNIEnv * env)) return InstanceKlass::is_finalization_enabled(); JVM_END @@ -2865,6 +2865,26 @@ static void thread_entry(JavaThread* thread, TRAPS) { JVM_ENTRY(void, JVM_StartThread(JNIEnv* env, jobject jthread)) +#if INCLUDE_CDS + if (DumpSharedSpaces) { + // During java -Xshare:dump, if we allow multiple Java threads to + // execute in parallel, symbols and classes may be loaded in + // random orders which will make the resulting CDS archive + // non-deterministic. + // + // Lucikly, during java -Xshare:dump, it's important to run only + // the code in the main Java thread (which is NOT started here) that + // creates the module graph, etc. It's safe to not start the other + // threads which are launched by class static initializers + // (ReferenceHandler, FinalizerThread and CleanerImpl). + if (log_is_enabled(Info, cds)) { + ResourceMark rm; + oop t = JNIHandles::resolve_non_null(jthread); + log_info(cds)("JVM_StartThread() ignored: %s", t->klass()->external_name()); + } + return; + } +#endif JavaThread *native_thread = NULL; // We cannot hold the Threads_lock when we throw an exception, @@ -3035,7 +3055,7 @@ JVM_ENTRY(void, JVM_SetThreadPriority(JNIEnv* env, jobject jthread, jint prio)) JVM_END -JVM_ENTRY(void, JVM_Yield(JNIEnv *env, jclass threadClass)) +JVM_LEAF(void, JVM_Yield(JNIEnv *env, jclass threadClass)) if (os::dont_yield()) return; HOTSPOT_THREAD_YIELD(); os::naked_yield(); @@ -3643,11 +3663,11 @@ JVM_ENTRY(jclass, JVM_LookupLambdaProxyClassFromArchive(JNIEnv* env, #endif // INCLUDE_CDS JVM_END -JVM_ENTRY(jboolean, JVM_IsCDSDumpingEnabled(JNIEnv* env)) +JVM_LEAF(jboolean, JVM_IsCDSDumpingEnabled(JNIEnv* env)) return Arguments::is_dumping_archive(); JVM_END -JVM_ENTRY(jboolean, JVM_IsSharingEnabled(JNIEnv* env)) +JVM_LEAF(jboolean, JVM_IsSharingEnabled(JNIEnv* env)) return UseSharedSpaces; JVM_END @@ -3673,7 +3693,7 @@ JVM_ENTRY_NO_ENV(jlong, JVM_GetRandomSeedForDumping()) } JVM_END -JVM_ENTRY(jboolean, JVM_IsDumpingClassList(JNIEnv *env)) +JVM_LEAF(jboolean, JVM_IsDumpingClassList(JNIEnv *env)) #if INCLUDE_CDS return ClassListWriter::is_enabled() || DynamicDumpSharedSpaces; #else @@ -3782,7 +3802,7 @@ JVM_ENTRY(jobjectArray, JVM_DumpThreads(JNIEnv *env, jclass threadClass, jobject JVM_END // JVM monitoring and management support -JVM_ENTRY_NO_ENV(void*, JVM_GetManagement(jint version)) +JVM_LEAF(void*, JVM_GetManagement(jint version)) return Management::get_jmm_interface(version); JVM_END @@ -3871,7 +3891,7 @@ JVM_ENTRY(jobjectArray, JVM_GetVmArguments(JNIEnv *env)) return (jobjectArray) JNIHandles::make_local(THREAD, result_h()); JVM_END -JVM_ENTRY_NO_ENV(jint, JVM_FindSignal(const char *name)) +JVM_LEAF(jint, JVM_FindSignal(const char *name)) return os::get_signal_number(name); JVM_END diff --git a/src/hotspot/share/prims/jvmtiRedefineClasses.cpp b/src/hotspot/share/prims/jvmtiRedefineClasses.cpp index 586c06791779239d14d1312367ab1a4c3b2a4e2c..e8ba72cbc0e02c7254b0f3e9a9d2ce2aa664a0fc 100644 --- a/src/hotspot/share/prims/jvmtiRedefineClasses.cpp +++ b/src/hotspot/share/prims/jvmtiRedefineClasses.cpp @@ -1856,14 +1856,15 @@ jvmtiError VM_RedefineClasses::merge_cp_and_rewrite( if (old_cp->has_dynamic_constant()) { scratch_cp->set_has_dynamic_constant(); } - // Copy attributes from scratch_cp to merge_cp - merge_cp->copy_fields(scratch_cp()); log_info(redefine, class, constantpool)("merge_cp_len=%d, index_map_len=%d", merge_cp_length, _index_map_count); if (_index_map_count == 0) { // there is nothing to map between the new and merged constant pools + // Copy attributes from scratch_cp to merge_cp + merge_cp->copy_fields(scratch_cp()); + if (old_cp->length() == scratch_cp->length()) { // The old and new constant pools are the same length and the // index map is empty. This means that the three constant pools @@ -1917,6 +1918,9 @@ jvmtiError VM_RedefineClasses::merge_cp_and_rewrite( return JVMTI_ERROR_INTERNAL; } + // Copy attributes from scratch_cp to merge_cp (should be done after rewrite_cp_refs()) + merge_cp->copy_fields(scratch_cp()); + // Replace the new constant pool with a shrunken copy of the // merged constant pool so now the rewritten bytecodes have // valid references; the previous new constant pool will get @@ -3492,10 +3496,9 @@ void VM_RedefineClasses::rewrite_cp_refs_in_verification_type_info( } // end rewrite_cp_refs_in_verification_type_info() -// Change the constant pool associated with klass scratch_class to -// scratch_cp. If shrink is true, then scratch_cp_length elements -// are copied from scratch_cp to a smaller constant pool and the -// smaller constant pool is associated with scratch_class. +// Change the constant pool associated with klass scratch_class to scratch_cp. +// scratch_cp_length elements are copied from scratch_cp to a smaller constant pool +// and the smaller constant pool is associated with scratch_class. void VM_RedefineClasses::set_new_constant_pool( ClassLoaderData* loader_data, InstanceKlass* scratch_class, constantPoolHandle scratch_cp, @@ -4357,10 +4360,6 @@ void VM_RedefineClasses::redefine_single_class(Thread* current, jclass the_jclas // Leave arrays of jmethodIDs and itable index cache unchanged - // Copy the "source file name" attribute from new class version - the_class->set_source_file_name_index( - scratch_class->source_file_name_index()); - // Copy the "source debug extension" attribute from new class version the_class->set_source_debug_extension( scratch_class->source_debug_extension(), diff --git a/src/hotspot/share/prims/methodHandles.cpp b/src/hotspot/share/prims/methodHandles.cpp index 5ae35e34a8c845b443c9f22a8a50ae0504b91a82..cb66076eeca4f879f01334ef605e541310ea9fee 100644 --- a/src/hotspot/share/prims/methodHandles.cpp +++ b/src/hotspot/share/prims/methodHandles.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2021, 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 @@ -89,7 +89,11 @@ void MethodHandles::generate_adapters() { ResourceMark rm; TraceTime timer("MethodHandles adapters generation", TRACETIME_LOG(Info, startuptime)); - _adapter_code = MethodHandlesAdapterBlob::create(adapter_code_size); + // The adapter entry is required to be aligned to CodeEntryAlignment. + // So we need additional bytes due to alignment. + int adapter_num = (int)Interpreter::method_handle_invoke_LAST - (int)Interpreter::method_handle_invoke_FIRST + 1; + int max_aligned_bytes = adapter_num * CodeEntryAlignment; + _adapter_code = MethodHandlesAdapterBlob::create(adapter_code_size + max_aligned_bytes); CodeBuffer code(_adapter_code); MethodHandlesAdapterGenerator g(&code); g.generate(); diff --git a/src/hotspot/share/runtime/abstract_vm_version.cpp b/src/hotspot/share/runtime/abstract_vm_version.cpp index bcde237bad7aa479d5de0166a1bb827ba3d1e270..319f1eba26bf3254fe5e013b3e68d7e98ce5faad 100644 --- a/src/hotspot/share/runtime/abstract_vm_version.cpp +++ b/src/hotspot/share/runtime/abstract_vm_version.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 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 @@ -198,11 +198,7 @@ const char* Abstract_VM_Version::internal_vm_info_string() { #ifndef HOTSPOT_BUILD_COMPILER #ifdef _MSC_VER - #if _MSC_VER == 1600 - #define HOTSPOT_BUILD_COMPILER "MS VC++ 10.0 (VS2010)" - #elif _MSC_VER == 1700 - #define HOTSPOT_BUILD_COMPILER "MS VC++ 11.0 (VS2012)" - #elif _MSC_VER == 1800 + #if _MSC_VER == 1800 #define HOTSPOT_BUILD_COMPILER "MS VC++ 12.0 (VS2013)" #elif _MSC_VER == 1900 #define HOTSPOT_BUILD_COMPILER "MS VC++ 14.0 (VS2015)" @@ -238,6 +234,10 @@ const char* Abstract_VM_Version::internal_vm_info_string() { #define HOTSPOT_BUILD_COMPILER "MS VC++ 16.8 / 16.9 (VS2019)" #elif _MSC_VER == 1929 #define HOTSPOT_BUILD_COMPILER "MS VC++ 16.10 / 16.11 (VS2019)" + #elif _MSC_VER == 1930 + #define HOTSPOT_BUILD_COMPILER "MS VC++ 17.0 (VS2022)" + #elif _MSC_VER == 1931 + #define HOTSPOT_BUILD_COMPILER "MS VC++ 17.1 (VS2022)" #else #define HOTSPOT_BUILD_COMPILER "unknown MS VC++:" XSTR(_MSC_VER) #endif diff --git a/src/hotspot/share/runtime/arguments.cpp b/src/hotspot/share/runtime/arguments.cpp index b65e25edbbc84fea5034ec82442e0009ed0ef13e..1d7fb5f983a507a5a01b6d66c35f7140a8328862 100644 --- a/src/hotspot/share/runtime/arguments.cpp +++ b/src/hotspot/share/runtime/arguments.cpp @@ -40,6 +40,7 @@ #include "logging/logStream.hpp" #include "logging/logTag.hpp" #include "memory/allocation.inline.hpp" +#include "metaprogramming/enableIf.hpp" #include "oops/instanceKlass.hpp" #include "oops/oop.inline.hpp" #include "prims/jvmtiExport.hpp" @@ -56,6 +57,7 @@ #include "services/management.hpp" #include "services/nmtCommon.hpp" #include "utilities/align.hpp" +#include "utilities/debug.hpp" #include "utilities/defaultStream.hpp" #include "utilities/macros.hpp" #include "utilities/powerOfTwo.hpp" @@ -63,6 +65,7 @@ #if INCLUDE_JFR #include "jfr/jfr.hpp" #endif +#include #define DEFAULT_JAVA_LAUNCHER "generic" @@ -538,6 +541,8 @@ static SpecialFlag const special_jvm_flags[] = { { "UseHeavyMonitors", JDK_Version::jdk(18), JDK_Version::jdk(19), JDK_Version::jdk(20) }, #endif { "ExtendedDTraceProbes", JDK_Version::jdk(19), JDK_Version::jdk(20), JDK_Version::jdk(21) }, + { "UseContainerCpuShares", JDK_Version::jdk(19), JDK_Version::jdk(20), JDK_Version::jdk(21) }, + { "PreferContainerQuotaForCPUCount", JDK_Version::jdk(19), JDK_Version::jdk(20), JDK_Version::jdk(21) }, // --- Deprecated alias flags (see also aliased_jvm_flags) - sorted by obsolete_in then expired_in: { "DefaultMaxRAMFraction", JDK_Version::jdk(8), JDK_Version::undefined(), JDK_Version::undefined() }, @@ -742,20 +747,84 @@ bool Arguments::verify_special_jvm_flags(bool check_globals) { } #endif -// Parses a size specification string. -bool Arguments::atojulong(const char *s, julong* result) { - julong n = 0; +template ::value), ENABLE_IF(sizeof(T) == 4)> // signed 32-bit +static bool parse_integer_impl(const char *s, char **endptr, int base, T* result) { + // Don't use strtol -- on 64-bit builds, "long" could be either 32- or 64-bits + // so the range tests could be tautological and might cause compiler warnings. + STATIC_ASSERT(sizeof(long long) >= 8); // C++ specification + errno = 0; // errno is thread safe + long long v = strtoll(s, endptr, base); + if (errno != 0 || v < min_jint || v > max_jint) { + return false; + } + *result = static_cast(v); + return true; +} + +template ::value), ENABLE_IF(sizeof(T) == 4)> // unsigned 32-bit +static bool parse_integer_impl(const char *s, char **endptr, int base, T* result) { + if (s[0] == '-') { + return false; + } + // Don't use strtoul -- same reason as above. + STATIC_ASSERT(sizeof(unsigned long long) >= 8); // C++ specification + errno = 0; // errno is thread safe + unsigned long long v = strtoull(s, endptr, base); + if (errno != 0 || v > max_juint) { + return false; + } + *result = static_cast(v); + return true; +} + +template ::value), ENABLE_IF(sizeof(T) == 8)> // signed 64-bit +static bool parse_integer_impl(const char *s, char **endptr, int base, T* result) { + errno = 0; // errno is thread safe + *result = strtoll(s, endptr, base); + return errno == 0; +} + +template ::value), ENABLE_IF(sizeof(T) == 8)> // unsigned 64-bit +static bool parse_integer_impl(const char *s, char **endptr, int base, T* result) { + if (s[0] == '-') { + return false; + } + errno = 0; // errno is thread safe + *result = strtoull(s, endptr, base); + return errno == 0; +} - // First char must be a digit. Don't allow negative numbers or leading spaces. - if (!isdigit(*s)) { +template +static bool multiply_by_1k(T& n) { + if (n >= std::numeric_limits::min() / 1024 && + n <= std::numeric_limits::max() / 1024) { + n *= 1024; + return true; + } else { + return false; + } +} + +// All of the integral types that can be used for command line options: +// int, uint, intx, uintx, uint64_t, size_t +// +// In all supported platforms, these types can be mapped to only 4 native types: +// {signed, unsigned} x {32-bit, 64-bit} +// +// We use SFINAE to pick the correct parse_integer_impl() function +template +static bool parse_integer(const char *s, T* result) { + if (!isdigit(s[0]) && s[0] != '-') { + // strtoll/strtoull may allow leading spaces. Forbid it. return false; } - bool is_hex = (s[0] == '0' && (s[1] == 'x' || s[1] == 'X')); + T n = 0; + bool is_hex = (s[0] == '0' && (s[1] == 'x' || s[1] == 'X')) || + (s[0] == '-' && s[1] == '0' && (s[2] == 'x' || s[3] == 'X')); char* remainder; - errno = 0; - n = strtoull(s, &remainder, (is_hex ? 16 : 10)); - if (errno != 0) { + + if (!parse_integer_impl(s, &remainder, (is_hex ? 16 : 10), &n)) { return false; } @@ -766,28 +835,29 @@ bool Arguments::atojulong(const char *s, julong* result) { switch (*remainder) { case 'T': case 't': - *result = n * G * K; - // Check for overflow. - if (*result/((julong)G * K) != n) return false; - return true; + if (!multiply_by_1k(n)) return false; + // fall-through case 'G': case 'g': - *result = n * G; - if (*result/G != n) return false; - return true; + if (!multiply_by_1k(n)) return false; + // fall-through case 'M': case 'm': - *result = n * M; - if (*result/M != n) return false; - return true; + if (!multiply_by_1k(n)) return false; + // fall-through case 'K': case 'k': - *result = n * K; - if (*result/K != n) return false; - return true; + if (!multiply_by_1k(n)) return false; + break; case '\0': - *result = n; - return true; + break; default: return false; } + + *result = n; + return true; +} + +bool Arguments::atojulong(const char *s, julong* result) { + return parse_integer(s, result); } Arguments::ArgsRange Arguments::check_memory_size(julong size, julong min_size, julong max_size) { @@ -836,57 +906,57 @@ static bool set_fp_numeric_flag(JVMFlag* flag, char* value, JVMFlagOrigin origin return false; } -static bool set_numeric_flag(JVMFlag* flag, char* value, JVMFlagOrigin origin) { - julong v; - int int_v; - intx intx_v; - bool is_neg = false; - +static JVMFlag::Error set_numeric_flag(JVMFlag* flag, char* value, JVMFlagOrigin origin) { if (flag == NULL) { - return false; + return JVMFlag::INVALID_FLAG; } - // Check the sign first since atojulong() parses only unsigned values. - if (*value == '-') { - if (!flag->is_intx() && !flag->is_int()) { - return false; - } - value++; - is_neg = true; - } - if (!Arguments::atojulong(value, &v)) { - return false; - } if (flag->is_int()) { - int_v = (int) v; - if (is_neg) { - int_v = -int_v; + int v; + if (parse_integer(value, &v)) { + return JVMFlagAccess::set_int(flag, &v, origin); } - return JVMFlagAccess::set_int(flag, &int_v, origin) == JVMFlag::SUCCESS; } else if (flag->is_uint()) { - uint uint_v = (uint) v; - return JVMFlagAccess::set_uint(flag, &uint_v, origin) == JVMFlag::SUCCESS; + uint v; + if (parse_integer(value, &v)) { + return JVMFlagAccess::set_uint(flag, &v, origin); + } } else if (flag->is_intx()) { - intx_v = (intx) v; - if (is_neg) { - intx_v = -intx_v; + intx v; + if (parse_integer(value, &v)) { + return JVMFlagAccess::set_intx(flag, &v, origin); } - return JVMFlagAccess::set_intx(flag, &intx_v, origin) == JVMFlag::SUCCESS; } else if (flag->is_uintx()) { - uintx uintx_v = (uintx) v; - return JVMFlagAccess::set_uintx(flag, &uintx_v, origin) == JVMFlag::SUCCESS; + uintx v; + if (parse_integer(value, &v)) { + return JVMFlagAccess::set_uintx(flag, &v, origin); + } } else if (flag->is_uint64_t()) { - uint64_t uint64_t_v = (uint64_t) v; - return JVMFlagAccess::set_uint64_t(flag, &uint64_t_v, origin) == JVMFlag::SUCCESS; + uint64_t v; + if (parse_integer(value, &v)) { + return JVMFlagAccess::set_uint64_t(flag, &v, origin); + } } else if (flag->is_size_t()) { - size_t size_t_v = (size_t) v; - return JVMFlagAccess::set_size_t(flag, &size_t_v, origin) == JVMFlag::SUCCESS; + size_t v; + if (parse_integer(value, &v)) { + return JVMFlagAccess::set_size_t(flag, &v, origin); + } } else if (flag->is_double()) { - double double_v = (double) v; - return JVMFlagAccess::set_double(flag, &double_v, origin) == JVMFlag::SUCCESS; - } else { - return false; + // This function parses only input strings without a decimal + // point character (.) + // If a string looks like a FP number, it would be parsed by + // set_fp_numeric_flag(). See Arguments::parse_argument(). + jlong v; + if (parse_integer(value, &v)) { + double double_v = (double) v; + if (value[0] == '-' && v == 0) { // special case: 0.0 is different than -0.0. + double_v = -0.0; + } + return JVMFlagAccess::set_double(flag, &double_v, origin); + } } + + return JVMFlag::WRONG_FORMAT; } static bool set_string_flag(JVMFlag* flag, const char* value, JVMFlagOrigin origin) { @@ -1048,7 +1118,7 @@ bool Arguments::parse_argument(const char* arg, JVMFlagOrigin origin) { return false; } JVMFlag* flag = JVMFlag::find_flag(real_name); - return set_numeric_flag(flag, value, origin); + return set_numeric_flag(flag, value, origin) == JVMFlag::SUCCESS; } return false; @@ -2065,24 +2135,16 @@ static const char* system_assertion_options[] = { bool Arguments::parse_uintx(const char* value, uintx* uintx_arg, uintx min_size) { - - // Check the sign first since atojulong() parses only unsigned values. - bool value_is_positive = !(*value == '-'); - - if (value_is_positive) { - julong n; - bool good_return = atojulong(value, &n); - if (good_return) { - bool above_minimum = n >= min_size; - bool value_is_too_large = n > max_uintx; - - if (above_minimum && !value_is_too_large) { - *uintx_arg = n; - return true; - } - } + uintx n; + if (!parse_integer(value, &n)) { + return false; + } + if (n >= min_size) { + *uintx_arg = n; + return true; + } else { + return false; } - return false; } bool Arguments::create_module_property(const char* prop_name, const char* prop_value, PropertyInternal internal) { @@ -2133,7 +2195,7 @@ Arguments::ArgsRange Arguments::parse_memory_size(const char* s, julong* long_arg, julong min_size, julong max_size) { - if (!atojulong(s, long_arg)) return arg_unreadable; + if (!parse_integer(s, long_arg)) return arg_unreadable; return check_memory_size(*long_arg, min_size, max_size); } diff --git a/src/hotspot/share/runtime/arguments.hpp b/src/hotspot/share/runtime/arguments.hpp index de6cf1a4d2343340e91c6e9138b0ec6b5f0187be..7910b366b38f1fcaa94b90e74fc19235aeaaf77b 100644 --- a/src/hotspot/share/runtime/arguments.hpp +++ b/src/hotspot/share/runtime/arguments.hpp @@ -237,6 +237,7 @@ class Arguments : AllStatic { friend class JvmtiExport; friend class CodeCacheExtensions; friend class ArgumentsTest; + friend class LargeOptionsTest; public: // Operation modi enum Mode { diff --git a/src/hotspot/share/runtime/flags/debug_globals.hpp b/src/hotspot/share/runtime/flags/debug_globals.hpp index 11ea2f6010457f13a0bd541cc8871807d7c8c900..177a4ae074b6224237beed091ec46ee09f45592d 100644 --- a/src/hotspot/share/runtime/flags/debug_globals.hpp +++ b/src/hotspot/share/runtime/flags/debug_globals.hpp @@ -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 @@ -62,6 +62,29 @@ product(ccstr, DummyManageableStringFlag, NULL, MANAGEABLE, \ "Dummy flag for testing string handling in WriteableFlags") \ \ + product(bool, TestFlagFor_bool, false, \ + "Used by VM internal regression tests only") \ + \ + product(int, TestFlagFor_int, 0, \ + "Used by VM internal regression tests only") \ + \ + product(uint, TestFlagFor_uint, 0, \ + "Used by VM internal regression tests only") \ + \ + product(intx, TestFlagFor_intx, 0, \ + "Used by VM internal regression tests only") \ + \ + product(uintx, TestFlagFor_uintx, 0, \ + "Used by VM internal regression tests only") \ + \ + product(uint64_t, TestFlagFor_uint64_t, 0, \ + "Used by VM internal regression tests only") \ + \ + product(size_t, TestFlagFor_size_t, 0, \ + "Used by VM internal regression tests only") \ + \ + product(double, TestFlagFor_double, 0.0, \ + "Used by VM internal regression tests only") \ // end of DEBUG_RUNTIME_FLAGS diff --git a/src/hotspot/share/runtime/frame.cpp b/src/hotspot/share/runtime/frame.cpp index 7a6456ef658a6e04d56f8257a598ad5e16c7cae6..4ca96e0c5a9c9fa78aacf3b3a0858bdec5e0087d 100644 --- a/src/hotspot/share/runtime/frame.cpp +++ b/src/hotspot/share/runtime/frame.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -1110,6 +1110,11 @@ void frame::verify(const RegisterMap* map) const { #ifdef ASSERT bool frame::verify_return_pc(address x) { +#ifdef TARGET_ARCH_aarch64 + if (!pauth_ptr_is_raw(x)) { + return false; + } +#endif if (StubRoutines::returns_to_call_stub(x)) { return true; } diff --git a/src/hotspot/share/runtime/frame.hpp b/src/hotspot/share/runtime/frame.hpp index e4eed4a1198114fabd88e6ecee93114dda9277ab..bc7d3d4775e6ec574288ca6711fcabd548951113 100644 --- a/src/hotspot/share/runtime/frame.hpp +++ b/src/hotspot/share/runtime/frame.hpp @@ -207,8 +207,12 @@ class frame { public: // Link (i.e., the pointer to the previous frame) + // might crash if the frame has no parent intptr_t* link() const; + // Link (i.e., the pointer to the previous frame) or null if the link cannot be accessed + intptr_t* link_or_null() const; + // Return address address sender_pc() const; diff --git a/src/hotspot/share/runtime/globals.hpp b/src/hotspot/share/runtime/globals.hpp index 7dd589b58c57fbaf6db496d8fffc6220886417d2..0ab10a117f1fa6211004b72f5da11562c2b4a1e1 100644 --- a/src/hotspot/share/runtime/globals.hpp +++ b/src/hotspot/share/runtime/globals.hpp @@ -1522,7 +1522,7 @@ const intx ObjectAlignmentInBytes = 8; "Stack space (bytes) required for JVM_InvokeMethod to complete") \ \ /* code cache parameters */ \ - develop_pd(uintx, CodeCacheSegmentSize, \ + product_pd(uintx, CodeCacheSegmentSize, EXPERIMENTAL, \ "Code cache segment size (in bytes) - smallest unit of " \ "allocation") \ range(1, 1024) \ diff --git a/src/hotspot/share/runtime/os.cpp b/src/hotspot/share/runtime/os.cpp index f86396beada4e173a3d423ff0f4736d5e12665a7..9ac8a99355623480f9d417f745fbf8714f5df9b7 100644 --- a/src/hotspot/share/runtime/os.cpp +++ b/src/hotspot/share/runtime/os.cpp @@ -634,6 +634,8 @@ void* os::malloc(size_t size, MEMFLAGS memflags, const NativeCallStack& stack) { // Special handling for NMT preinit phase before arguments are parsed void* rc = NULL; if (NMTPreInit::handle_malloc(&rc, size)) { + // No need to fill with 0 because DumpSharedSpaces doesn't use these + // early allocations. return rc; } @@ -649,22 +651,22 @@ void* os::malloc(size_t size, MEMFLAGS memflags, const NativeCallStack& stack) { return NULL; } - const NMT_TrackingLevel level = MemTracker::tracking_level(); - const size_t nmt_overhead = - MemTracker::malloc_header_size(level) + MemTracker::malloc_footer_size(level); + const size_t outer_size = size + MemTracker::overhead_per_malloc(); - const size_t outer_size = size + nmt_overhead; - - void* const outer_ptr = (u_char*)::malloc(outer_size); + void* const outer_ptr = ::malloc(outer_size); if (outer_ptr == NULL) { return NULL; } - void* inner_ptr = MemTracker::record_malloc((address)outer_ptr, size, memflags, stack, level); + void* const inner_ptr = MemTracker::record_malloc((address)outer_ptr, size, memflags, stack); - DEBUG_ONLY(::memset(inner_ptr, uninitBlockPad, size);) + if (DumpSharedSpaces) { + // Need to deterministically fill all the alignment gaps in C++ structures. + ::memset(inner_ptr, 0, size); + } else { + DEBUG_ONLY(::memset(inner_ptr, uninitBlockPad, size);) + } DEBUG_ONLY(break_if_ptr_caught(inner_ptr);) - return inner_ptr; } @@ -696,19 +698,17 @@ void* os::realloc(void *memblock, size_t size, MEMFLAGS memflags, const NativeCa return NULL; } - const NMT_TrackingLevel level = MemTracker::tracking_level(); - const size_t nmt_overhead = - MemTracker::malloc_header_size(level) + MemTracker::malloc_footer_size(level); - - const size_t new_outer_size = size + nmt_overhead; + const size_t new_outer_size = size + MemTracker::overhead_per_malloc(); // If NMT is enabled, this checks for heap overwrites, then de-accounts the old block. - void* const old_outer_ptr = MemTracker::record_free(memblock, level); + void* const old_outer_ptr = MemTracker::record_free(memblock); void* const new_outer_ptr = ::realloc(old_outer_ptr, new_outer_size); + if (new_outer_ptr == NULL) { + return NULL; + } - // If NMT is enabled, this checks for heap overwrites, then de-accounts the old block. - void* const new_inner_ptr = MemTracker::record_malloc(new_outer_ptr, size, memflags, stack, level); + void* const new_inner_ptr = MemTracker::record_malloc(new_outer_ptr, size, memflags, stack); DEBUG_ONLY(break_if_ptr_caught(new_inner_ptr);) @@ -728,10 +728,9 @@ void os::free(void *memblock) { DEBUG_ONLY(break_if_ptr_caught(memblock);) - const NMT_TrackingLevel level = MemTracker::tracking_level(); - // If NMT is enabled, this checks for heap overwrites, then de-accounts the old block. - void* const old_outer_ptr = MemTracker::record_free(memblock, level); + void* const old_outer_ptr = MemTracker::record_free(memblock); + ::free(old_outer_ptr); } @@ -1174,34 +1173,34 @@ void os::print_location(outputStream* st, intptr_t x, bool verbose) { st->print_cr(INTPTR_FORMAT " is an unknown value", p2i(addr)); } +bool is_pointer_bad(intptr_t* ptr) { + return !is_aligned(ptr, sizeof(uintptr_t)) || !os::is_readable_pointer(ptr); +} + // Looks like all platforms can use the same function to check if C // stack is walkable beyond current frame. +// Returns true if this is not the case, i.e. the frame is possibly +// the first C frame on the stack. bool os::is_first_C_frame(frame* fr) { #ifdef _WINDOWS return true; // native stack isn't walkable on windows this way. #endif - // Load up sp, fp, sender sp and sender fp, check for reasonable values. // Check usp first, because if that's bad the other accessors may fault // on some architectures. Ditto ufp second, etc. - uintptr_t fp_align_mask = (uintptr_t)(sizeof(address)-1); - // sp on amd can be 32 bit aligned. - uintptr_t sp_align_mask = (uintptr_t)(sizeof(int)-1); - uintptr_t usp = (uintptr_t)fr->sp(); - if ((usp & sp_align_mask) != 0) return true; + if (is_pointer_bad(fr->sp())) return true; uintptr_t ufp = (uintptr_t)fr->fp(); - if ((ufp & fp_align_mask) != 0) return true; + if (is_pointer_bad(fr->fp())) return true; uintptr_t old_sp = (uintptr_t)fr->sender_sp(); - if ((old_sp & sp_align_mask) != 0) return true; - if (old_sp == 0 || old_sp == (uintptr_t)-1) return true; + if ((uintptr_t)fr->sender_sp() == (uintptr_t)-1 || is_pointer_bad(fr->sender_sp())) return true; - uintptr_t old_fp = (uintptr_t)fr->link(); - if ((old_fp & fp_align_mask) != 0) return true; - if (old_fp == 0 || old_fp == (uintptr_t)-1 || old_fp == ufp) return true; + uintptr_t old_fp = (uintptr_t)fr->link_or_null(); + if (old_fp == 0 || old_fp == (uintptr_t)-1 || old_fp == ufp || + is_pointer_bad(fr->link_or_null())) return true; // stack grows downwards; if old_fp is below current fp or if the stack // frame is too large, either the stack is corrupted or fp is not saved @@ -1213,7 +1212,6 @@ bool os::is_first_C_frame(frame* fr) { return false; } - // Set up the boot classpath. char* os::format_boot_path(const char* format_string, diff --git a/src/hotspot/share/runtime/safefetch.inline.hpp b/src/hotspot/share/runtime/safefetch.inline.hpp index 79c833e4db6b086c58e9903bf39a9509aa2c0f44..cee0853573cf5a323ce26a59e73f5b6de4cf2246 100644 --- a/src/hotspot/share/runtime/safefetch.inline.hpp +++ b/src/hotspot/share/runtime/safefetch.inline.hpp @@ -54,10 +54,20 @@ inline intptr_t SafeFetchN(intptr_t* adr, intptr_t errValue) { // returns true if SafeFetch32 and SafeFetchN can be used safely (stubroutines are already generated) inline bool CanUseSafeFetch32() { +#if defined (__APPLE__) && defined(AARCH64) + if (Thread::current_or_null_safe() == NULL) { // workaround for JDK-8282475 + return false; + } +#endif // __APPLE__ && AARCH64 return StubRoutines::SafeFetch32_stub() ? true : false; } inline bool CanUseSafeFetchN() { +#if defined (__APPLE__) && defined(AARCH64) + if (Thread::current_or_null_safe() == NULL) { + return false; + } +#endif // __APPLE__ && AARCH64 return StubRoutines::SafeFetchN_stub() ? true : false; } diff --git a/src/hotspot/share/runtime/sharedRuntime.cpp b/src/hotspot/share/runtime/sharedRuntime.cpp index a5de65ea5ab94c9ae2e36be412c666c535e495f2..ce9a06265a9fc88e593603bdca1bd07ba3bfe4cd 100644 --- a/src/hotspot/share/runtime/sharedRuntime.cpp +++ b/src/hotspot/share/runtime/sharedRuntime.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -1947,6 +1947,8 @@ bool SharedRuntime::should_fixup_call_destination(address destination, address e JRT_LEAF(void, SharedRuntime::fixup_callers_callsite(Method* method, address caller_pc)) Method* moop(method); + AARCH64_PORT_ONLY(assert(pauth_ptr_is_raw(caller_pc), "should be raw")); + address entry_point = moop->from_compiled_entry_no_trampoline(); // It's possible that deoptimization can occur at a call site which hasn't diff --git a/src/hotspot/share/runtime/stubRoutines.cpp b/src/hotspot/share/runtime/stubRoutines.cpp index 591950fa213f0b5bc8430b666044e400ba09943e..c378ab09dc8d76bc50f2629e224561ab6aba0b14 100644 --- a/src/hotspot/share/runtime/stubRoutines.cpp +++ b/src/hotspot/share/runtime/stubRoutines.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -215,7 +215,10 @@ void StubRoutines::initialize1() { if (_code1 == NULL) { ResourceMark rm; TraceTime timer("StubRoutines generation 1", TRACETIME_LOG(Info, startuptime)); - _code1 = BufferBlob::create("StubRoutines (1)", code_size1); + // Add extra space for large CodeEntryAlignment + int max_aligned_stubs = 10; + int size = code_size1 + CodeEntryAlignment * max_aligned_stubs; + _code1 = BufferBlob::create("StubRoutines (1)", size); if (_code1 == NULL) { vm_exit_out_of_memory(code_size1, OOM_MALLOC_ERROR, "CodeCache: no room for StubRoutines (1)"); } @@ -269,7 +272,10 @@ void StubRoutines::initialize2() { if (_code2 == NULL) { ResourceMark rm; TraceTime timer("StubRoutines generation 2", TRACETIME_LOG(Info, startuptime)); - _code2 = BufferBlob::create("StubRoutines (2)", code_size2); + // Add extra space for large CodeEntryAlignment + int max_aligned_stubs = 100; + int size = code_size2 + CodeEntryAlignment * max_aligned_stubs; + _code2 = BufferBlob::create("StubRoutines (2)", size); if (_code2 == NULL) { vm_exit_out_of_memory(code_size2, OOM_MALLOC_ERROR, "CodeCache: no room for StubRoutines (2)"); } diff --git a/src/hotspot/share/runtime/sweeper.cpp b/src/hotspot/share/runtime/sweeper.cpp index ec39455924725342529c15d4afe57b46a4a7def5..988d6ccfac95199f75c49cc932cbcb647eea9f7c 100644 --- a/src/hotspot/share/runtime/sweeper.cpp +++ b/src/hotspot/share/runtime/sweeper.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -229,19 +229,19 @@ void NMethodSweeper::sweeper_loop() { /** * Wakes up the sweeper thread to sweep if code cache space runs low */ -void NMethodSweeper::report_allocation(int code_blob_type) { - if (should_start_aggressive_sweep(code_blob_type)) { +void NMethodSweeper::report_allocation() { + if (should_start_aggressive_sweep()) { MonitorLocker waiter(CodeSweeper_lock, Mutex::_no_safepoint_check_flag); _should_sweep = true; CodeSweeper_lock->notify(); } } -bool NMethodSweeper::should_start_aggressive_sweep(int code_blob_type) { +bool NMethodSweeper::should_start_aggressive_sweep() { // Makes sure that we do not invoke the sweeper too often during startup. double start_threshold = 100.0 / (double)StartAggressiveSweepingAt; double aggressive_sweep_threshold = MAX2(start_threshold, 1.1); - return (CodeCache::reverse_free_ratio(code_blob_type) >= aggressive_sweep_threshold); + return (CodeCache::reverse_free_ratio() >= aggressive_sweep_threshold); } /** @@ -546,8 +546,7 @@ void NMethodSweeper::possibly_flush(nmethod* nm) { // ReservedCodeCacheSize int reset_val = hotness_counter_reset_val(); int time_since_reset = reset_val - nm->hotness_counter(); - int code_blob_type = CodeCache::get_code_blob_type(nm); - double threshold = -reset_val + (CodeCache::reverse_free_ratio(code_blob_type) * NmethodSweepActivity); + double threshold = -reset_val + (CodeCache::reverse_free_ratio() * NmethodSweepActivity); // The less free space in the code cache we have - the bigger reverse_free_ratio() is. // I.e., 'threshold' increases with lower available space in the code cache and a higher // NmethodSweepActivity. If the current hotness counter - which decreases from its initial diff --git a/src/hotspot/share/runtime/sweeper.hpp b/src/hotspot/share/runtime/sweeper.hpp index ecf5a353cfd1cbde22c7c3bc1988c0f8c77fccde..06daf37ee3a7e5757a0b6000c140bcfabf2f0e5e 100644 --- a/src/hotspot/share/runtime/sweeper.hpp +++ b/src/hotspot/share/runtime/sweeper.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -113,11 +113,11 @@ class NMethodSweeper : public AllStatic { static CodeBlobClosure* prepare_mark_active_nmethods(); static void sweeper_loop(); - static bool should_start_aggressive_sweep(int code_blob_type); + static bool should_start_aggressive_sweep(); static void force_sweep(); static int hotness_counter_reset_val(); static void report_state_change(nmethod* nm); - static void report_allocation(int code_blob_type); // Possibly start the sweeper thread. + static void report_allocation(); // Possibly start the sweeper thread. static void possibly_flush(nmethod* nm); static void print(outputStream* out); // Printing/debugging static void print() { print(tty); } diff --git a/src/hotspot/share/runtime/thread.cpp b/src/hotspot/share/runtime/thread.cpp index 0ec50849f5a5f6936e964268cb2babd4ecd63e61..c1e327d40a5f00a54623b9f56d1a67be52ea1d5e 100644 --- a/src/hotspot/share/runtime/thread.cpp +++ b/src/hotspot/share/runtime/thread.cpp @@ -336,10 +336,10 @@ void Thread::call_run() { // Perform common initialization actions - register_thread_stack_with_NMT(); - MACOS_AARCH64_ONLY(this->init_wx()); + register_thread_stack_with_NMT(); + JFR_ONLY(Jfr::on_thread_start(this);) log_debug(os, thread)("Thread " UINTX_FORMAT " stack dimensions: " @@ -1373,23 +1373,24 @@ void JavaThread::exit(bool destroy_vm, ExitType exit_type) { } } - // Call Thread.exit(). We try 3 times in case we got another Thread.stop during - // the execution of the method. If that is not enough, then we don't really care. Thread.stop - // is deprecated anyhow. if (!is_Compiler_thread()) { - int count = 3; - while (java_lang_Thread::threadGroup(threadObj()) != NULL && (count-- > 0)) { - EXCEPTION_MARK; - JavaValue result(T_VOID); - Klass* thread_klass = vmClasses::Thread_klass(); - JavaCalls::call_virtual(&result, - threadObj, thread_klass, - vmSymbols::exit_method_name(), - vmSymbols::void_method_signature(), - THREAD); - CLEAR_PENDING_EXCEPTION; - } + // We have finished executing user-defined Java code and now have to do the + // implementation specific clean-up by calling Thread.exit(). We prevent any + // asynchronous exceptions from being delivered while in Thread.exit() + // to ensure the clean-up is not corrupted. + NoAsyncExceptionDeliveryMark _no_async(this); + + EXCEPTION_MARK; + JavaValue result(T_VOID); + Klass* thread_klass = vmClasses::Thread_klass(); + JavaCalls::call_virtual(&result, + threadObj, thread_klass, + vmSymbols::exit_method_name(), + vmSymbols::void_method_signature(), + THREAD); + CLEAR_PENDING_EXCEPTION; } + // notify JVMTI if (JvmtiExport::should_post_thread_life()) { JvmtiExport::post_thread_end(this); @@ -1592,7 +1593,7 @@ void JavaThread::check_and_handle_async_exceptions() { // If we are at a polling page safepoint (not a poll return) // then we must defer async exception because live registers // will be clobbered by the exception path. Poll return is - // ok because the call we a returning from already collides + // ok because the call we are returning from already collides // with exception handling registers and so there is no issue. // (The exception handling path kills call result registers but // this is ok since the exception kills the result anyway). @@ -1613,6 +1614,9 @@ void JavaThread::check_and_handle_async_exceptions() { } if (!clear_async_exception_condition()) { + if ((_suspend_flags & _async_delivery_disabled) != 0) { + log_info(exceptions)("Async exception delivery is disabled"); + } return; } diff --git a/src/hotspot/share/runtime/thread.hpp b/src/hotspot/share/runtime/thread.hpp index 151d487355a8c24514217147a95480722f023fb3..4256a44c39c4c217eeee57b915cb53f8cbeddaea 100644 --- a/src/hotspot/share/runtime/thread.hpp +++ b/src/hotspot/share/runtime/thread.hpp @@ -785,9 +785,10 @@ class JavaThread: public Thread { enum SuspendFlags { // NOTE: avoid using the sign-bit as cc generates different test code // when the sign-bit is used, and sometimes incorrectly - see CR 6398077 - _has_async_exception = 0x00000001U, // there is a pending async exception - _trace_flag = 0x00000004U, // call tracing backend - _obj_deopt = 0x00000008U // suspend for object reallocation and relocking for JVMTI agent + _has_async_exception = 0x00000001U, // there is a pending async exception + _async_delivery_disabled = 0x00000002U, // async exception delivery is disabled + _trace_flag = 0x00000004U, // call tracing backend + _obj_deopt = 0x00000008U // suspend for object reallocation and relocking for JVMTI agent }; // various suspension related flags - atomically updated @@ -815,7 +816,8 @@ class JavaThread: public Thread { inline bool clear_async_exception_condition(); public: bool has_async_exception_condition() { - return (_suspend_flags & _has_async_exception) != 0; + return (_suspend_flags & _has_async_exception) != 0 && + (_suspend_flags & _async_delivery_disabled) == 0; } inline void set_pending_async_exception(oop e); inline void set_pending_unsafe_access_error(); @@ -823,6 +825,13 @@ class JavaThread: public Thread { void send_thread_stop(oop throwable); void check_and_handle_async_exceptions(); + class NoAsyncExceptionDeliveryMark : public StackObj { + friend JavaThread; + JavaThread *_target; + inline NoAsyncExceptionDeliveryMark(JavaThread *t); + inline ~NoAsyncExceptionDeliveryMark(); + }; + // Safepoint support public: // Expose _thread_state for SafeFetchInt() volatile JavaThreadState _thread_state; @@ -1323,14 +1332,15 @@ class JavaThread: public Thread { // external JNI entry points where the JNIEnv is passed into the VM. static JavaThread* thread_from_jni_environment(JNIEnv* env) { JavaThread* current = (JavaThread*)((intptr_t)env - in_bytes(jni_environment_offset())); - // We can't get here in a thread that has completed its execution and so - // "is_terminated", but a thread is also considered terminated if the VM + // We can't normally get here in a thread that has completed its + // execution and so "is_terminated", except when the call is from + // AsyncGetCallTrace, which can be triggered by a signal at any point in + // a thread's lifecycle. A thread is also considered terminated if the VM // has exited, so we have to check this and block in case this is a daemon // thread returning to the VM (the JNI DirectBuffer entry points rely on // this). if (current->is_terminated()) { current->block_if_vm_exited(); - ShouldNotReachHere(); } return current; } diff --git a/src/hotspot/share/runtime/thread.inline.hpp b/src/hotspot/share/runtime/thread.inline.hpp index 7d27a3bf257cacbeb075f15dac7e60611108ac35..cdb8d9abb230752d3f186d19e701147669064b2b 100644 --- a/src/hotspot/share/runtime/thread.inline.hpp +++ b/src/hotspot/share/runtime/thread.inline.hpp @@ -124,7 +124,9 @@ inline void JavaThread::clear_obj_deopt_flag() { inline bool JavaThread::clear_async_exception_condition() { bool ret = has_async_exception_condition(); - clear_suspend_flag(_has_async_exception); + if (ret) { + clear_suspend_flag(_has_async_exception); + } return ret; } @@ -138,6 +140,15 @@ inline void JavaThread::set_pending_unsafe_access_error() { DEBUG_ONLY(_is_unsafe_access_error = true); } + +inline JavaThread::NoAsyncExceptionDeliveryMark::NoAsyncExceptionDeliveryMark(JavaThread *t) : _target(t) { + assert((_target->_suspend_flags & _async_delivery_disabled) == 0, "Nesting is not supported"); + _target->set_suspend_flag(_async_delivery_disabled); +} +inline JavaThread::NoAsyncExceptionDeliveryMark::~NoAsyncExceptionDeliveryMark() { + _target->clear_suspend_flag(_async_delivery_disabled); +} + inline JavaThreadState JavaThread::thread_state() const { #if defined(PPC64) || defined (AARCH64) // Use membars when accessing volatile _thread_state. See diff --git a/src/hotspot/share/runtime/vmOperation.hpp b/src/hotspot/share/runtime/vmOperation.hpp index 5489770f38693174887a50de8f45f53282922ca3..e6e9f3f645727b65da763b4bb08ceb911aa23342 100644 --- a/src/hotspot/share/runtime/vmOperation.hpp +++ b/src/hotspot/share/runtime/vmOperation.hpp @@ -95,6 +95,7 @@ template(CleanClassLoaderDataMetaspaces) \ template(PrintCompileQueue) \ template(PrintClassHierarchy) \ + template(PrintClasses) \ template(ICBufferFull) \ template(PrintMetadata) \ template(GTestExecuteAtSafepoint) \ diff --git a/src/hotspot/share/services/diagnosticCommand.cpp b/src/hotspot/share/services/diagnosticCommand.cpp index 06b9539a94d7dc2533d8fac8ca67ec3cefd04a1e..725d801613429171236d9b2669a291ce62c331e1 100644 --- a/src/hotspot/share/services/diagnosticCommand.cpp +++ b/src/hotspot/share/services/diagnosticCommand.cpp @@ -26,6 +26,7 @@ #include "jvm.h" #include "classfile/classLoaderHierarchyDCmd.hpp" #include "classfile/classLoaderStats.hpp" +#include "classfile/classLoaderDataGraph.hpp" #include "classfile/javaClasses.hpp" #include "classfile/systemDictionary.hpp" #include "classfile/vmClasses.hpp" @@ -102,6 +103,7 @@ void DCmdRegistrant::register_dcmds(){ DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(full_export, true, false)); DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(full_export, true, false)); DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(full_export, true, false)); + DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(full_export, true, false)); DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(full_export, true, false)); DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(full_export, true, false)); DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(full_export, true, false)); @@ -954,6 +956,41 @@ void TouchedMethodsDCmd::execute(DCmdSource source, TRAPS) { VMThread::execute(&dumper); } +ClassesDCmd::ClassesDCmd(outputStream* output, bool heap) : + DCmdWithParser(output, heap), + _verbose("-verbose", + "Dump the detailed content of a Java class. " + "Some classes are annotated with flags: " + "F = has, or inherits, a non-empty finalize method, " + "f = has final method, " + "W = methods rewritten, " + "C = marked with @Contended annotation, " + "R = has been redefined, " + "S = is shared class", + "BOOLEAN", false, "false") { + _dcmdparser.add_dcmd_option(&_verbose); +} + +class VM_PrintClasses : public VM_Operation { +private: + outputStream* _out; + bool _verbose; +public: + VM_PrintClasses(outputStream* out, bool verbose) : _out(out), _verbose(verbose) {} + + virtual VMOp_Type type() const { return VMOp_PrintClasses; } + + virtual void doit() { + PrintClassClosure closure(_out, _verbose); + ClassLoaderDataGraph::classes_do(&closure); + } +}; + +void ClassesDCmd::execute(DCmdSource source, TRAPS) { + VM_PrintClasses vmop(output(), _verbose.is_set()); + VMThread::execute(&vmop); +} + #if INCLUDE_CDS DumpSharedArchiveDCmd::DumpSharedArchiveDCmd(outputStream* output, bool heap) : DCmdWithParser(output, heap), diff --git a/src/hotspot/share/services/diagnosticCommand.hpp b/src/hotspot/share/services/diagnosticCommand.hpp index d276a3ca7569cef4524cda7c43943a6af28e3495..dfcdc783f88c0298723f331da67a1b6afcade4b8 100644 --- a/src/hotspot/share/services/diagnosticCommand.hpp +++ b/src/hotspot/share/services/diagnosticCommand.hpp @@ -858,6 +858,28 @@ public: virtual void execute(DCmdSource source, TRAPS); }; +class ClassesDCmd : public DCmdWithParser { +protected: + DCmdArgument _verbose; +public: + ClassesDCmd(outputStream* output, bool heap); + static const char* name() { + return "VM.classes"; + } + static const char* description() { + return "Print all loaded classes"; + } + static const char* impact() { + return "Medium: Depends on number of loaded classes."; + } + static const JavaPermission permission() { + JavaPermission p = {"java.lang.management.ManagementPermission", + "monitor", NULL}; + return p; + } + virtual void execute(DCmdSource source, TRAPS); +}; + #if INCLUDE_JVMTI class DebugOnCmdStartDCmd : public DCmd { public: diff --git a/src/hotspot/share/services/dtraceAttacher.hpp b/src/hotspot/share/services/dtraceAttacher.hpp deleted file mode 100644 index 1faf1adfaf0291950c5f863cbab0daf9c9a64f50..0000000000000000000000000000000000000000 --- a/src/hotspot/share/services/dtraceAttacher.hpp +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (c) 2006, 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. - * - */ - -#ifndef SHARE_SERVICES_DTRACEATTACHER_HPP -#define SHARE_SERVICES_DTRACEATTACHER_HPP - -#define DTRACE_ALLOC_PROBES 0x1 -#define DTRACE_METHOD_PROBES 0x2 -#define DTRACE_MONITOR_PROBES 0x4 -#define DTRACE_ALL_PROBES (DTRACE_ALLOC_PROBES | \ - DTRACE_METHOD_PROBES | \ - DTRACE_MONITOR_PROBES) - -class DTrace : public AllStatic { - private: - // disable one or more probes - OR above constants - static void disable_dprobes(int probe_types); - - public: - // enable one or more probes - OR above constants - static void enable_dprobes(int probe_types); - // all clients detached, do any clean-up - static void detach_all_clients(); - // set ExtendedDTraceProbes flag - static void set_extended_dprobes(bool value); - // set DTraceMonitorProbes flag - static void set_monitor_dprobes(bool value); -}; - -#endif // SHARE_SERVICES_DTRACEATTACHER_HPP diff --git a/src/hotspot/share/services/heapDumper.cpp b/src/hotspot/share/services/heapDumper.cpp index 8f83e129b94e789e090ee999e44961978a3d8376..7204270393611f35c78e318ea01caa237570ef1d 100644 --- a/src/hotspot/share/services/heapDumper.cpp +++ b/src/hotspot/share/services/heapDumper.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2021, 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 @@ -912,12 +912,10 @@ class DumperSupport : AllStatic { static void dump_instance_field_descriptors(AbstractDumpWriter* writer, Klass* k); // creates HPROF_GC_INSTANCE_DUMP record for the given object static void dump_instance(AbstractDumpWriter* writer, oop o); - // creates HPROF_GC_CLASS_DUMP record for the given class and each of its - // array classes - static void dump_class_and_array_classes(AbstractDumpWriter* writer, Klass* k); - // creates HPROF_GC_CLASS_DUMP record for a given primitive array - // class (and each multi-dimensional array class too) - static void dump_basic_type_array_class(AbstractDumpWriter* writer, Klass* k); + // creates HPROF_GC_CLASS_DUMP record for the given instance class + static void dump_instance_class(AbstractDumpWriter* writer, Klass* k); + // creates HPROF_GC_CLASS_DUMP record for a given array class + static void dump_array_class(AbstractDumpWriter* writer, Klass* k); // creates HPROF_GC_OBJ_ARRAY_DUMP record for the given object array static void dump_object_array(AbstractDumpWriter* writer, objArrayOop array); @@ -1243,9 +1241,8 @@ void DumperSupport::dump_instance(AbstractDumpWriter* writer, oop o) { writer->end_sub_record(); } -// creates HPROF_GC_CLASS_DUMP record for the given class and each of -// its array classes -void DumperSupport::dump_class_and_array_classes(AbstractDumpWriter* writer, Klass* k) { +// creates HPROF_GC_CLASS_DUMP record for the given instance class +void DumperSupport::dump_instance_class(AbstractDumpWriter* writer, Klass* k) { InstanceKlass* ik = InstanceKlass::cast(k); // We can safepoint and do a heap dump at a point where we have a Klass, @@ -1298,73 +1295,42 @@ void DumperSupport::dump_class_and_array_classes(AbstractDumpWriter* writer, Kla dump_instance_field_descriptors(writer, ik); writer->end_sub_record(); +} - // array classes - k = ik->array_klass_or_null(); - while (k != NULL) { - assert(k->is_objArray_klass(), "not an ObjArrayKlass"); - - u4 size = 1 + sizeof(address) + 4 + 6 * sizeof(address) + 4 + 2 + 2 + 2; - writer->start_sub_record(HPROF_GC_CLASS_DUMP, size); - writer->write_classID(k); - writer->write_u4(STACK_TRACE_ID); - - // super class of array classes is java.lang.Object - java_super = k->java_super(); - assert(java_super != NULL, "checking"); - writer->write_classID(java_super); - - writer->write_objectID(ik->class_loader()); - writer->write_objectID(ik->signers()); - writer->write_objectID(ik->protection_domain()); - - writer->write_objectID(oop(NULL)); // reserved - writer->write_objectID(oop(NULL)); - writer->write_u4(0); // instance size - writer->write_u2(0); // constant pool - writer->write_u2(0); // static fields - writer->write_u2(0); // instance fields - - writer->end_sub_record(); - - // get the array class for the next rank - k = k->array_klass_or_null(); +// creates HPROF_GC_CLASS_DUMP record for the given array class +void DumperSupport::dump_array_class(AbstractDumpWriter* writer, Klass* k) { + InstanceKlass* ik = NULL; // bottom class for object arrays, NULL for primitive type arrays + if (k->is_objArray_klass()) { + Klass *bk = ObjArrayKlass::cast(k)->bottom_klass(); + assert(bk != NULL, "checking"); + if (bk->is_instance_klass()) { + ik = InstanceKlass::cast(bk); + } } -} -// creates HPROF_GC_CLASS_DUMP record for a given primitive array -// class (and each multi-dimensional array class too) -void DumperSupport::dump_basic_type_array_class(AbstractDumpWriter* writer, Klass* k) { - // array classes - while (k != NULL) { - Klass* klass = k; - - u4 size = 1 + sizeof(address) + 4 + 6 * sizeof(address) + 4 + 2 + 2 + 2; - writer->start_sub_record(HPROF_GC_CLASS_DUMP, size); - writer->write_classID(klass); - writer->write_u4(STACK_TRACE_ID); - - // super class of array classes is java.lang.Object - InstanceKlass* java_super = klass->java_super(); - assert(java_super != NULL, "checking"); - writer->write_classID(java_super); + u4 size = 1 + sizeof(address) + 4 + 6 * sizeof(address) + 4 + 2 + 2 + 2; + writer->start_sub_record(HPROF_GC_CLASS_DUMP, size); + writer->write_classID(k); + writer->write_u4(STACK_TRACE_ID); - writer->write_objectID(oop(NULL)); // loader - writer->write_objectID(oop(NULL)); // signers - writer->write_objectID(oop(NULL)); // protection domain + // super class of array classes is java.lang.Object + InstanceKlass* java_super = k->java_super(); + assert(java_super != NULL, "checking"); + writer->write_classID(java_super); - writer->write_objectID(oop(NULL)); // reserved - writer->write_objectID(oop(NULL)); - writer->write_u4(0); // instance size - writer->write_u2(0); // constant pool - writer->write_u2(0); // static fields - writer->write_u2(0); // instance fields + writer->write_objectID(ik == NULL ? oop(NULL) : ik->class_loader()); + writer->write_objectID(ik == NULL ? oop(NULL) : ik->signers()); + writer->write_objectID(ik == NULL ? oop(NULL) : ik->protection_domain()); - writer->end_sub_record(); + writer->write_objectID(oop(NULL)); // reserved + writer->write_objectID(oop(NULL)); + writer->write_u4(0); // instance size + writer->write_u2(0); // constant pool + writer->write_u2(0); // static fields + writer->write_u2(0); // instance fields + + writer->end_sub_record(); - // get the array class for the next rank - k = klass->array_klass_or_null(); - } } // Hprof uses an u4 as record length field, @@ -1936,17 +1902,11 @@ class VM_HeapDumper : public VM_GC_Operation, public WorkerTask { bool skip_operation() const; // writes a HPROF_LOAD_CLASS record - class ClassesDo; static void do_load_class(Klass* k); // writes a HPROF_GC_CLASS_DUMP record for the given class - // (and each array class too) static void do_class_dump(Klass* k); - // writes a HPROF_GC_CLASS_DUMP records for a given basic type - // array (and each multi-dimensional array too) - static void do_basic_type_array_class_dump(Klass* k); - // HPROF_GC_ROOT_THREAD_OBJ records int do_thread(JavaThread* thread, u4 thread_serial_num); void do_threads(); @@ -2027,52 +1987,40 @@ void DumperSupport::end_of_dump(AbstractDumpWriter* writer) { writer->write_u4(0); } -// writes a HPROF_LOAD_CLASS record for the class (and each of its -// array classes) +// writes a HPROF_LOAD_CLASS record for the class void VM_HeapDumper::do_load_class(Klass* k) { static u4 class_serial_num = 0; // len of HPROF_LOAD_CLASS record u4 remaining = 2*oopSize + 2*sizeof(u4); - // write a HPROF_LOAD_CLASS for the class and each array class - do { - DumperSupport::write_header(writer(), HPROF_LOAD_CLASS, remaining); - - // class serial number is just a number - writer()->write_u4(++class_serial_num); + DumperSupport::write_header(writer(), HPROF_LOAD_CLASS, remaining); - // class ID - Klass* klass = k; - writer()->write_classID(klass); + // class serial number is just a number + writer()->write_u4(++class_serial_num); - // add the Klass* and class serial number pair - dumper()->add_class_serial_number(klass, class_serial_num); + // class ID + writer()->write_classID(k); - writer()->write_u4(STACK_TRACE_ID); + // add the Klass* and class serial number pair + dumper()->add_class_serial_number(k, class_serial_num); - // class name ID - Symbol* name = klass->name(); - writer()->write_symbolID(name); + writer()->write_u4(STACK_TRACE_ID); - // write a LOAD_CLASS record for the array type (if it exists) - k = klass->array_klass_or_null(); - } while (k != NULL); + // class name ID + Symbol* name = k->name(); + writer()->write_symbolID(name); } // writes a HPROF_GC_CLASS_DUMP record for the given class void VM_HeapDumper::do_class_dump(Klass* k) { if (k->is_instance_klass()) { - DumperSupport::dump_class_and_array_classes(writer(), k); + DumperSupport::dump_instance_class(writer(), k); + } else { + DumperSupport::dump_array_class(writer(), k); } } -// writes a HPROF_GC_CLASS_DUMP records for a given basic type -// array (and each multi-dimensional array too) -void VM_HeapDumper::do_basic_type_array_class_dump(Klass* k) { - DumperSupport::dump_basic_type_array_class(writer(), k); -} - // Walk the stack of the given thread. // Dumps a HPROF_GC_ROOT_JAVA_FRAME record for each local // Dumps a HPROF_GC_ROOT_JNI_LOCAL record for each JNI local @@ -2291,7 +2239,6 @@ void VM_HeapDumper::work(uint worker_id) { LockedClassesDo locked_load_classes(&do_load_class); ClassLoaderDataGraph::classes_do(&locked_load_classes); } - Universe::basic_type_classes_do(&do_load_class); // write HPROF_FRAME and HPROF_TRACE records // this must be called after _klass_map is built when iterating the classes above. @@ -2302,7 +2249,6 @@ void VM_HeapDumper::work(uint worker_id) { LockedClassesDo locked_dump_class(&do_class_dump); ClassLoaderDataGraph::classes_do(&locked_dump_class); } - Universe::basic_type_classes_do(&do_basic_type_array_class_dump); // HPROF_GC_ROOT_THREAD_OBJ + frames + jni locals do_threads(); diff --git a/src/hotspot/share/services/mallocSiteTable.cpp b/src/hotspot/share/services/mallocSiteTable.cpp index 2670c138daa159ebacc4d3fd63963507b48dbad6..f8d30e1dca91895596a459e7a94c1264f1052153 100644 --- a/src/hotspot/share/services/mallocSiteTable.cpp +++ b/src/hotspot/share/services/mallocSiteTable.cpp @@ -106,13 +106,11 @@ bool MallocSiteTable::walk(MallocSiteWalker* walker) { * 2. Overflow hash bucket. * Under any of above circumstances, caller should handle the situation. */ -MallocSite* MallocSiteTable::lookup_or_add(const NativeCallStack& key, size_t* bucket_idx, - size_t* pos_idx, MEMFLAGS flags) { +MallocSite* MallocSiteTable::lookup_or_add(const NativeCallStack& key, uint32_t* marker, MEMFLAGS flags) { assert(flags != mtNone, "Should have a real memory type"); const unsigned int hash = key.calculate_hash(); const unsigned int index = hash_to_index(hash); - *bucket_idx = (size_t)index; - *pos_idx = 0; + *marker = 0; // First entry for this hash bucket if (_table[index] == NULL) { @@ -122,41 +120,47 @@ MallocSite* MallocSiteTable::lookup_or_add(const NativeCallStack& key, size_t* b // swap in the head if (Atomic::replace_if_null(&_table[index], entry)) { + *marker = build_marker(index, 0); return entry->data(); } delete entry; } + unsigned pos_idx = 0; MallocSiteHashtableEntry* head = _table[index]; - while (head != NULL && (*pos_idx) <= MAX_BUCKET_LENGTH) { + while (head != NULL && pos_idx < MAX_BUCKET_LENGTH) { if (head->hash() == hash) { MallocSite* site = head->data(); if (site->flag() == flags && site->equals(key)) { + *marker = build_marker(index, pos_idx); return head->data(); } } - if (head->next() == NULL && (*pos_idx) < MAX_BUCKET_LENGTH) { + if (head->next() == NULL && pos_idx < (MAX_BUCKET_LENGTH - 1)) { MallocSiteHashtableEntry* entry = new_entry(key, flags); // OOM check if (entry == NULL) return NULL; if (head->atomic_insert(entry)) { - (*pos_idx) ++; + pos_idx ++; + *marker = build_marker(index, pos_idx); return entry->data(); } // contended, other thread won delete entry; } head = (MallocSiteHashtableEntry*)head->next(); - (*pos_idx) ++; + pos_idx ++; } return NULL; } // Access malloc site -MallocSite* MallocSiteTable::malloc_site(size_t bucket_idx, size_t pos_idx) { +MallocSite* MallocSiteTable::malloc_site(uint32_t marker) { + uint16_t bucket_idx = bucket_idx_from_marker(marker); assert(bucket_idx < table_size, "Invalid bucket index"); + const uint16_t pos_idx = pos_idx_from_marker(marker); MallocSiteHashtableEntry* head = _table[bucket_idx]; for (size_t index = 0; index < pos_idx && head != NULL; diff --git a/src/hotspot/share/services/mallocSiteTable.hpp b/src/hotspot/share/services/mallocSiteTable.hpp index 814b70c6473a5dba8fecf56892c3295b5413844e..0511a557d419ef6a5c3da9038f3ab89d42c2d8d3 100644 --- a/src/hotspot/share/services/mallocSiteTable.hpp +++ b/src/hotspot/share/services/mallocSiteTable.hpp @@ -111,11 +111,22 @@ class MallocSiteTable : AllStatic { table_size = (table_base_size * NMT_TrackingStackDepth - 1) }; - // The table must not be wider than the maximum value the bucket_idx field - // in the malloc header can hold. + // Table cannot be wider than a 16bit bucket idx can hold +#define MAX_MALLOCSITE_TABLE_SIZE (USHRT_MAX - 1) + // Each bucket chain cannot be longer than what a 16 bit pos idx can hold (hopefully way shorter) +#define MAX_BUCKET_LENGTH (USHRT_MAX - 1) + STATIC_ASSERT(table_size <= MAX_MALLOCSITE_TABLE_SIZE); + static uint32_t build_marker(unsigned bucket_idx, unsigned pos_idx) { + assert(bucket_idx <= MAX_MALLOCSITE_TABLE_SIZE && pos_idx < MAX_BUCKET_LENGTH, "overflow"); + return (uint32_t)bucket_idx << 16 | pos_idx; + } + static uint16_t bucket_idx_from_marker(uint32_t marker) { return marker >> 16; } + static uint16_t pos_idx_from_marker(uint32_t marker) { return marker & 0xFFFF; } + public: + static bool initialize(); // Number of hash buckets @@ -123,9 +134,8 @@ class MallocSiteTable : AllStatic { // Access and copy a call stack from this table. Shared lock should be // acquired before access the entry. - static inline bool access_stack(NativeCallStack& stack, size_t bucket_idx, - size_t pos_idx) { - MallocSite* site = malloc_site(bucket_idx, pos_idx); + static inline bool access_stack(NativeCallStack& stack, uint32_t marker) { + MallocSite* site = malloc_site(marker); if (site != NULL) { stack = *site->call_stack(); return true; @@ -134,23 +144,22 @@ class MallocSiteTable : AllStatic { } // Record a new allocation from specified call path. - // Return true if the allocation is recorded successfully, bucket_idx - // and pos_idx are also updated to indicate the entry where the allocation - // information was recorded. + // Return true if the allocation is recorded successfully and updates marker + // to indicate the entry where the allocation information was recorded. // Return false only occurs under rare scenarios: // 1. out of memory // 2. overflow hash bucket static inline bool allocation_at(const NativeCallStack& stack, size_t size, - size_t* bucket_idx, size_t* pos_idx, MEMFLAGS flags) { - MallocSite* site = lookup_or_add(stack, bucket_idx, pos_idx, flags); + uint32_t* marker, MEMFLAGS flags) { + MallocSite* site = lookup_or_add(stack, marker, flags); if (site != NULL) site->allocate(size); return site != NULL; } - // Record memory deallocation. bucket_idx and pos_idx indicate where the allocation + // Record memory deallocation. marker indicates where the allocation // information was recorded. - static inline bool deallocation_at(size_t size, size_t bucket_idx, size_t pos_idx) { - MallocSite* site = malloc_site(bucket_idx, pos_idx); + static inline bool deallocation_at(size_t size, uint32_t marker) { + MallocSite* site = malloc_site(marker); if (site != NULL) { site->deallocate(size); return true; @@ -170,8 +179,8 @@ class MallocSiteTable : AllStatic { // Delete a bucket linked list static void delete_linked_list(MallocSiteHashtableEntry* head); - static MallocSite* lookup_or_add(const NativeCallStack& key, size_t* bucket_idx, size_t* pos_idx, MEMFLAGS flags); - static MallocSite* malloc_site(size_t bucket_idx, size_t pos_idx); + static MallocSite* lookup_or_add(const NativeCallStack& key, uint32_t* marker, MEMFLAGS flags); + static MallocSite* malloc_site(uint32_t marker); static bool walk(MallocSiteWalker* walker); static inline unsigned int hash_to_index(unsigned int hash) { diff --git a/src/hotspot/share/services/mallocTracker.cpp b/src/hotspot/share/services/mallocTracker.cpp index 04cf12be94f115732a53059406ad82c96397dc01..ff0d1d14f6dbb84a3eb991581e427b5830e08043 100644 --- a/src/hotspot/share/services/mallocTracker.cpp +++ b/src/hotspot/share/services/mallocTracker.cpp @@ -27,7 +27,6 @@ #include "runtime/safefetch.inline.hpp" #include "services/mallocSiteTable.hpp" #include "services/mallocTracker.hpp" -#include "services/mallocTracker.inline.hpp" #include "services/memTracker.hpp" #include "utilities/debug.hpp" #include "utilities/ostream.hpp" @@ -115,20 +114,6 @@ void MallocHeader::mark_block_as_dead() { set_footer(_footer_canary_dead_mark); } -void MallocHeader::release() { - assert(MemTracker::enabled(), "Sanity"); - - assert_block_integrity(); - - MallocMemorySummary::record_free(size(), flags()); - MallocMemorySummary::record_free_malloc_header(sizeof(MallocHeader)); - if (MemTracker::tracking_level() == NMT_detail) { - MallocSiteTable::deallocation_at(size(), _bucket_idx, _pos_idx); - } - - mark_block_as_dead(); -} - void MallocHeader::print_block_on_error(outputStream* st, address bad_address) const { assert(bad_address >= (address)this, "sanity"); @@ -233,13 +218,8 @@ bool MallocHeader::check_block_integrity(char* msg, size_t msglen, address* p_co return true; } -bool MallocHeader::record_malloc_site(const NativeCallStack& stack, size_t size, - size_t* bucket_idx, size_t* pos_idx, MEMFLAGS flags) const { - return MallocSiteTable::allocation_at(stack, size, bucket_idx, pos_idx, flags); -} - bool MallocHeader::get_stack(NativeCallStack& stack) const { - return MallocSiteTable::access_stack(stack, _bucket_idx, _pos_idx); + return MallocSiteTable::access_stack(stack, _mst_marker); } bool MallocTracker::initialize(NMT_TrackingLevel level) { @@ -255,29 +235,33 @@ bool MallocTracker::initialize(NMT_TrackingLevel level) { // Record a malloc memory allocation void* MallocTracker::record_malloc(void* malloc_base, size_t size, MEMFLAGS flags, - const NativeCallStack& stack, NMT_TrackingLevel level) { - assert(level != NMT_off, "precondition"); - void* memblock; // the address for user data - MallocHeader* header = NULL; - - if (malloc_base == NULL) { - return NULL; + const NativeCallStack& stack) +{ + assert(MemTracker::enabled(), "precondition"); + assert(malloc_base != NULL, "precondition"); + + MallocMemorySummary::record_malloc(size, flags); + MallocMemorySummary::record_new_malloc_header(sizeof(MallocHeader)); + uint32_t mst_marker = 0; + if (MemTracker::tracking_level() == NMT_detail) { + MallocSiteTable::allocation_at(stack, size, &mst_marker, flags); } // Uses placement global new operator to initialize malloc header - - header = ::new (malloc_base)MallocHeader(size, flags, stack, level); - memblock = (void*)((char*)malloc_base + sizeof(MallocHeader)); + MallocHeader* const header = ::new (malloc_base)MallocHeader(size, flags, stack, mst_marker); + void* const memblock = (void*)((char*)malloc_base + sizeof(MallocHeader)); // The alignment check: 8 bytes alignment for 32 bit systems. // 16 bytes alignment for 64-bit systems. assert(((size_t)memblock & (sizeof(size_t) * 2 - 1)) == 0, "Alignment check"); #ifdef ASSERT - if (level > NMT_off) { - // Read back - assert(get_size(memblock) == size, "Wrong size"); - assert(get_flags(memblock) == flags, "Wrong flags"); + // Read back + { + MallocHeader* const header2 = malloc_header(memblock); + assert(header2->size() == size, "Wrong size"); + assert(header2->flags() == flags, "Wrong flags"); + header2->assert_block_integrity(); } #endif @@ -285,9 +269,20 @@ void* MallocTracker::record_malloc(void* malloc_base, size_t size, MEMFLAGS flag } void* MallocTracker::record_free(void* memblock) { - assert(MemTracker::tracking_level() != NMT_off && memblock != NULL, "precondition"); - MallocHeader* header = malloc_header(memblock); - header->release(); + assert(MemTracker::enabled(), "Sanity"); + assert(memblock != NULL, "precondition"); + + MallocHeader* const header = malloc_header(memblock); + header->assert_block_integrity(); + + MallocMemorySummary::record_free(header->size(), header->flags()); + MallocMemorySummary::record_free_malloc_header(sizeof(MallocHeader)); + if (MemTracker::tracking_level() == NMT_detail) { + MallocSiteTable::deallocation_at(header->size(), header->mst_marker()); + } + + header->mark_block_as_dead(); + return (void*)header; } @@ -300,7 +295,7 @@ bool MallocTracker::print_pointer_information(const void* p, outputStream* st) { assert(MemTracker::enabled(), "NMT must be enabled"); if (CanUseSafeFetch32() && os::is_readable_pointer(p)) { const NMT_TrackingLevel tracking_level = MemTracker::tracking_level(); - const MallocHeader* mhdr = (const MallocHeader*)MallocTracker::get_base(const_cast(p), tracking_level); + const MallocHeader* mhdr = malloc_header(p); char msg[256]; address p_corrupted; if (os::is_readable_pointer(mhdr) && diff --git a/src/hotspot/share/services/mallocTracker.hpp b/src/hotspot/share/services/mallocTracker.hpp index 78e20c30f15e53d128736e004aa55b9f6654b70f..a0e09ee066eaf5e81d6b2df349a85e0972dabcfb 100644 --- a/src/hotspot/share/services/mallocTracker.hpp +++ b/src/hotspot/share/services/mallocTracker.hpp @@ -267,7 +267,7 @@ class MallocMemorySummary : AllStatic { * * 8 9 10 11 12 13 14 15 16 ++ * +--------+--------+--------+--------+--------+--------+--------+--------+ ------------------------ - * ... | bucket idx | pos idx | flags | unused | canary | ... User payload .... + * ... | malloc site table marker | flags | unused | canary | ... User payload .... * +--------+--------+--------+--------+--------+--------+--------+--------+ ------------------------ * * Layout on 32-bit: @@ -279,7 +279,7 @@ class MallocMemorySummary : AllStatic { * * 8 9 10 11 12 13 14 15 16 ++ * +--------+--------+--------+--------+--------+--------+--------+--------+ ------------------------ - * ... | bucket idx | pos idx | flags | unused | canary | ... User payload .... + * ... | malloc site table marker | flags | unused | canary | ... User payload .... * +--------+--------+--------+--------+--------+--------+--------+--------+ ------------------------ * * Notes: @@ -294,16 +294,12 @@ class MallocMemorySummary : AllStatic { class MallocHeader { NOT_LP64(uint32_t _alt_canary); - size_t _size; - uint16_t _bucket_idx; - uint16_t _pos_idx; - uint8_t _flags; - uint8_t _unused; + const size_t _size; + const uint32_t _mst_marker; + const uint8_t _flags; + const uint8_t _unused; uint16_t _canary; -#define MAX_MALLOCSITE_TABLE_SIZE (USHRT_MAX - 1) -#define MAX_BUCKET_LENGTH (USHRT_MAX - 1) - static const uint16_t _header_canary_life_mark = 0xE99E; static const uint16_t _header_canary_dead_mark = 0xD99D; static const uint16_t _footer_canary_life_mark = 0xE88E; @@ -314,11 +310,7 @@ class MallocHeader { // We discount sizes larger than these static const size_t max_reasonable_malloc_size = LP64_ONLY(256 * G) NOT_LP64(3500 * M); - // If block is broken, print out a report to tty (optionally with - // hex dump surrounding the broken block), then trigger a fatal error - void assert_block_integrity() const; void print_block_on_error(outputStream* st, address bad_address) const; - void mark_block_as_dead(); static uint16_t build_footer(uint8_t b1, uint8_t b2) { return ((uint16_t)b1 << 8) | (uint16_t)b2; } @@ -328,51 +320,32 @@ class MallocHeader { public: - MallocHeader(size_t size, MEMFLAGS flags, const NativeCallStack& stack, NMT_TrackingLevel level) { + MallocHeader(size_t size, MEMFLAGS flags, const NativeCallStack& stack, uint32_t mst_marker) + : _size(size), _mst_marker(mst_marker), _flags(NMTUtil::flag_to_index(flags)), + _unused(0), _canary(_header_canary_life_mark) + { assert(size < max_reasonable_malloc_size, "Too large allocation size?"); - - _flags = NMTUtil::flag_to_index(flags); - set_size(size); - if (level == NMT_detail) { - size_t bucket_idx; - size_t pos_idx; - if (record_malloc_site(stack, size, &bucket_idx, &pos_idx, flags)) { - assert(bucket_idx <= MAX_MALLOCSITE_TABLE_SIZE, "Overflow bucket index"); - assert(pos_idx <= MAX_BUCKET_LENGTH, "Overflow bucket position index"); - _bucket_idx = (uint16_t)bucket_idx; - _pos_idx = (uint16_t)pos_idx; - } - } - - _unused = 0; - _canary = _header_canary_life_mark; // On 32-bit we have some bits more, use them for a second canary // guarding the start of the header. NOT_LP64(_alt_canary = _header_alt_canary_life_mark;) set_footer(_footer_canary_life_mark); // set after initializing _size - - MallocMemorySummary::record_malloc(size, flags); - MallocMemorySummary::record_new_malloc_header(sizeof(MallocHeader)); } inline size_t size() const { return _size; } inline MEMFLAGS flags() const { return (MEMFLAGS)_flags; } + inline uint32_t mst_marker() const { return _mst_marker; } bool get_stack(NativeCallStack& stack) const; - // Cleanup tracking information and mark block as dead before the memory is released. - void release(); + void mark_block_as_dead(); // If block is broken, fill in a short descriptive text in out, // an option pointer to the corruption in p_corruption, and return false. // Return true if block is fine. bool check_block_integrity(char* msg, size_t msglen, address* p_corruption) const; - private: - inline void set_size(size_t size) { - _size = size; - } - bool record_malloc_site(const NativeCallStack& stack, size_t size, - size_t* bucket_idx, size_t* pos_idx, MEMFLAGS flags) const; + // If block is broken, print out a report to tty (optionally with + // hex dump surrounding the broken block), then trigger a fatal error + void assert_block_integrity() const; }; // This needs to be true on both 64-bit and 32-bit platforms @@ -385,15 +358,9 @@ class MallocTracker : AllStatic { // Initialize malloc tracker for specific tracking level static bool initialize(NMT_TrackingLevel level); - // malloc tracking header size for specific tracking level - static inline size_t malloc_header_size(NMT_TrackingLevel level) { - return (level == NMT_off) ? 0 : sizeof(MallocHeader); - } - - // malloc tracking footer size for specific tracking level - static inline size_t malloc_footer_size(NMT_TrackingLevel level) { - return (level == NMT_off) ? 0 : sizeof(uint16_t); - } + // The overhead that is incurred by switching on NMT (we need, per malloc allocation, + // space for header and 16-bit footer) + static const size_t overhead_per_malloc = sizeof(MallocHeader) + sizeof(uint16_t); // Parameter name convention: // memblock : the beginning address for user data @@ -405,30 +372,11 @@ class MallocTracker : AllStatic { // Record malloc on specified memory block static void* record_malloc(void* malloc_base, size_t size, MEMFLAGS flags, - const NativeCallStack& stack, NMT_TrackingLevel level); + const NativeCallStack& stack); // Record free on specified memory block static void* record_free(void* memblock); - // Offset memory address to header address - static inline void* get_base(void* memblock); - static inline void* get_base(void* memblock, NMT_TrackingLevel level) { - if (memblock == NULL || level == NMT_off) return memblock; - return (char*)memblock - malloc_header_size(level); - } - - // Get memory size - static inline size_t get_size(void* memblock) { - MallocHeader* header = malloc_header(memblock); - return header->size(); - } - - // Get memory type - static inline MEMFLAGS get_flags(void* memblock) { - MallocHeader* header = malloc_header(memblock); - return header->flags(); - } - static inline void record_new_arena(MEMFLAGS flags) { MallocMemorySummary::record_new_arena(flags); } @@ -451,8 +399,11 @@ class MallocTracker : AllStatic { private: static inline MallocHeader* malloc_header(void *memblock) { assert(memblock != NULL, "NULL pointer"); - MallocHeader* header = (MallocHeader*)((char*)memblock - sizeof(MallocHeader)); - return header; + return (MallocHeader*)((char*)memblock - sizeof(MallocHeader)); + } + static inline const MallocHeader* malloc_header(const void *memblock) { + assert(memblock != NULL, "NULL pointer"); + return (const MallocHeader*)((const char*)memblock - sizeof(MallocHeader)); } }; diff --git a/src/hotspot/share/services/memTracker.cpp b/src/hotspot/share/services/memTracker.cpp index 1037ec27418b951ee17f33a3f8bd7086a979a854..343703213ad6a4d7fdc9c6ee609b1959a8b1b212 100644 --- a/src/hotspot/share/services/memTracker.cpp +++ b/src/hotspot/share/services/memTracker.cpp @@ -33,7 +33,7 @@ #include "runtime/vmOperations.hpp" #include "services/memBaseline.hpp" #include "services/memReporter.hpp" -#include "services/mallocTracker.inline.hpp" +#include "services/mallocTracker.hpp" #include "services/memTracker.hpp" #include "services/nmtCommon.hpp" #include "services/nmtPreInit.hpp" @@ -90,10 +90,6 @@ void MemTracker::initialize() { } } -void* MemTracker::malloc_base(void* memblock) { - return MallocTracker::get_base(memblock); -} - void Tracker::record(address addr, size_t size) { if (MemTracker::tracking_level() < NMT_summary) return; switch(_type) { diff --git a/src/hotspot/share/services/memTracker.hpp b/src/hotspot/share/services/memTracker.hpp index 06d5c0c94a892813c95ac3c62ae0b3a12aff943e..97ec9abd9f583a4e24dd3d77d40ca2639ae3788e 100644 --- a/src/hotspot/share/services/memTracker.hpp +++ b/src/hotspot/share/services/memTracker.hpp @@ -31,6 +31,7 @@ #include "services/nmtCommon.hpp" #include "services/threadStackTracker.hpp" #include "services/virtualMemoryTracker.hpp" +#include "utilities/debug.hpp" #include "utilities/nativeCallStack.hpp" #define CURRENT_PC ((MemTracker::tracking_level() == NMT_detail) ? \ @@ -87,38 +88,30 @@ class MemTracker : AllStatic { return _tracking_level > NMT_off; } + // Per-malloc overhead incurred by NMT, depending on the current NMT level + static size_t overhead_per_malloc() { + return enabled() ? MallocTracker::overhead_per_malloc : 0; + } + static inline void* record_malloc(void* mem_base, size_t size, MEMFLAGS flag, - const NativeCallStack& stack, NMT_TrackingLevel level) { - if (level != NMT_off) { - return MallocTracker::record_malloc(mem_base, size, flag, stack, level); + const NativeCallStack& stack) { + assert(mem_base != NULL, "caller should handle NULL"); + if (enabled()) { + return MallocTracker::record_malloc(mem_base, size, flag, stack); } return mem_base; } - static inline size_t malloc_header_size(NMT_TrackingLevel level) { - return MallocTracker::malloc_header_size(level); - } - - // malloc tracking footer size for specific tracking level - static inline size_t malloc_footer_size(NMT_TrackingLevel level) { - return MallocTracker::malloc_footer_size(level); - } - - // To malloc base address, which is the starting address - // of malloc tracking header if tracking is enabled. - // Otherwise, it returns the same address. - static void* malloc_base(void* memblock); - // Record malloc free and return malloc base address - static inline void* record_free(void* memblock, NMT_TrackingLevel level) { + static inline void* record_free(void* memblock) { // Never turned on - if (level == NMT_off || memblock == NULL) { + assert(memblock != NULL, "caller should handle NULL"); + if (!enabled()) { return memblock; } return MallocTracker::record_free(memblock); } - // Record creation of an arena static inline void record_new_arena(MEMFLAGS flag) { if (!enabled()) return; diff --git a/src/hotspot/share/services/nmtCommon.hpp b/src/hotspot/share/services/nmtCommon.hpp index dc85338c025a0fe74efc0c406210d51b7cd8593d..f25e5cfd8c95f58a1d93da616b158e456235c83d 100644 --- a/src/hotspot/share/services/nmtCommon.hpp +++ b/src/hotspot/share/services/nmtCommon.hpp @@ -87,7 +87,7 @@ class NMTUtil : AllStatic { // Map memory type to index static inline int flag_to_index(MEMFLAGS flag) { - assert(flag_is_valid(flag), "Invalid flag"); + assert(flag_is_valid(flag), "Invalid flag (%u)", (unsigned)flag); return static_cast(flag); } @@ -98,7 +98,7 @@ class NMTUtil : AllStatic { // Map an index to memory type static MEMFLAGS index_to_flag(int index) { - assert(flag_index_is_valid(index), "Invalid flag"); + assert(flag_index_is_valid(index), "Invalid flag index (%d)", index); return static_cast(index); } diff --git a/src/hotspot/share/utilities/copy.hpp b/src/hotspot/share/utilities/copy.hpp index 12f59ad1311b3c9d481e761a08b92e5eb5b6ee5f..8c77f4d735bf19a5eadf7a02ea2dc84c9df2962a 100644 --- a/src/hotspot/share/utilities/copy.hpp +++ b/src/hotspot/share/utilities/copy.hpp @@ -26,6 +26,7 @@ #define SHARE_UTILITIES_COPY_HPP #include "oops/oopsHierarchy.hpp" +#include "runtime/atomic.hpp" #include "runtime/globals.hpp" #include "utilities/align.hpp" #include "utilities/bytes.hpp" @@ -297,6 +298,28 @@ class Copy : AllStatic { pd_zero_to_bytes(to, count); } + protected: + inline static void shared_disjoint_words_atomic(const HeapWord* from, + HeapWord* to, size_t count) { + + switch (count) { + case 8: Atomic::store(&to[7], Atomic::load(&from[7])); + case 7: Atomic::store(&to[6], Atomic::load(&from[6])); + case 6: Atomic::store(&to[5], Atomic::load(&from[5])); + case 5: Atomic::store(&to[4], Atomic::load(&from[4])); + case 4: Atomic::store(&to[3], Atomic::load(&from[3])); + case 3: Atomic::store(&to[2], Atomic::load(&from[2])); + case 2: Atomic::store(&to[1], Atomic::load(&from[1])); + case 1: Atomic::store(&to[0], Atomic::load(&from[0])); + case 0: break; + default: + while (count-- > 0) { + Atomic::store(to++, Atomic::load(from++)); + } + break; + } + } + private: static bool params_disjoint(const HeapWord* from, HeapWord* to, size_t count) { if (from < to) { diff --git a/src/hotspot/share/utilities/debug.cpp b/src/hotspot/share/utilities/debug.cpp index e8d95ebec1c4c7b57985ea62963b9d306d7dd062..a35770f2c52677ea84be60e44d4049f65a76dff1 100644 --- a/src/hotspot/share/utilities/debug.cpp +++ b/src/hotspot/share/utilities/debug.cpp @@ -478,6 +478,10 @@ extern "C" JNIEXPORT void verify() { extern "C" JNIEXPORT void pp(void* p) { Command c("pp"); FlagSetting fl(DisplayVMOutput, true); + if (p == NULL) { + tty->print_cr("NULL"); + return; + } if (Universe::heap()->is_in(p)) { oop obj = cast_to_oop(p); obj->print(); diff --git a/src/hotspot/share/utilities/exceptions.cpp b/src/hotspot/share/utilities/exceptions.cpp index 4ddc8e18ae6620bab8d8a8108f04a2585a3e14c5..1b56009a27d70a54df3d621426eba597811f0763 100644 --- a/src/hotspot/share/utilities/exceptions.cpp +++ b/src/hotspot/share/utilities/exceptions.cpp @@ -538,7 +538,11 @@ void Exceptions::debug_check_abort(const char *value_string, const char* message strstr(value_string, AbortVMOnException)) { if (AbortVMOnExceptionMessage == NULL || (message != NULL && strstr(message, AbortVMOnExceptionMessage))) { - fatal("Saw %s, aborting", value_string); + if (message == NULL) { + fatal("Saw %s, aborting", value_string); + } else { + fatal("Saw %s: %s, aborting", value_string, message); + } } } } diff --git a/src/hotspot/share/utilities/exceptions.hpp b/src/hotspot/share/utilities/exceptions.hpp index 1ff750c103a958f01a8383deeed4be75d86b20b2..a599682e25bf234788a715feb9f1a443d72efdf8 100644 --- a/src/hotspot/share/utilities/exceptions.hpp +++ b/src/hotspot/share/utilities/exceptions.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 @@ -56,7 +56,7 @@ class methodHandle; // The ThreadShadow class is a helper class to access the _pending_exception // field of the Thread class w/o having access to the Thread's interface (for -// include hierachy reasons). +// include hierarchy reasons). class ThreadShadow: public CHeapObj { friend class VMStructs; diff --git a/src/hotspot/share/utilities/globalDefinitions.hpp b/src/hotspot/share/utilities/globalDefinitions.hpp index 1b0b90e70fc00397e455b70644b54dd22141e7f4..fdd3db8875ad3295490ae050c1691bb5d54d0f5a 100644 --- a/src/hotspot/share/utilities/globalDefinitions.hpp +++ b/src/hotspot/share/utilities/globalDefinitions.hpp @@ -1219,5 +1219,9 @@ template bool primitive_equals(const K& k0, const K& k1) { return k0 == k1; } +//---------------------------------------------------------------------------------------------------- + +// Allow use of C++ thread_local when approved - see JDK-8282469. +#define APPROVED_CPP_THREAD_LOCAL thread_local #endif // SHARE_UTILITIES_GLOBALDEFINITIONS_HPP diff --git a/src/hotspot/share/utilities/macros.hpp b/src/hotspot/share/utilities/macros.hpp index 9207e8a1739c8b2a8e75ee9b71a3711a993c398a..8dea1a754faa2166fcd78870782ffb2155c7aa69 100644 --- a/src/hotspot/share/utilities/macros.hpp +++ b/src/hotspot/share/utilities/macros.hpp @@ -512,7 +512,7 @@ // Note: There are two ARM ports. They set the following in the makefiles: // 1. 32-bit port: -DARM -DARM32 -DTARGET_ARCH_arm -// 2. 64-bit port: -DAARCH64 -D_LP64 -DTARGET_ARCH_aaarch64 +// 2. 64-bit port: -DAARCH64 -D_LP64 -DTARGET_ARCH_aarch64 #ifdef ARM #define ARM_ONLY(code) code #define NOT_ARM(code) @@ -537,6 +537,12 @@ #define NOT_AARCH64(code) code #endif +#ifdef TARGET_ARCH_aarch64 +#define AARCH64_PORT_ONLY(code) code +#else +#define AARCH64_PORT_ONLY(code) +#endif + #define MACOS_AARCH64_ONLY(x) MACOS_ONLY(AARCH64_ONLY(x)) #ifdef VM_LITTLE_ENDIAN diff --git a/src/hotspot/share/utilities/vmError.cpp b/src/hotspot/share/utilities/vmError.cpp index 1d72092f8ae6f52592715565f13b9f5a6a18fe5f..984c57a13ec5715685ebeeeeea47fb6abe818bfb 100644 --- a/src/hotspot/share/utilities/vmError.cpp +++ b/src/hotspot/share/utilities/vmError.cpp @@ -115,7 +115,7 @@ static const char* env_list[] = { "DYLD_INSERT_LIBRARIES", // defined on Windows - "OS", "PROCESSOR_IDENTIFIER", "_ALT_JAVA_HOME_DIR", + "OS", "PROCESSOR_IDENTIFIER", "_ALT_JAVA_HOME_DIR", "TMP", "TEMP", (const char *)0 }; @@ -910,7 +910,7 @@ void VMError::report(outputStream* st, bool _verbose) { STEP("printing code blobs if possible") - if (_verbose && _context) { + if (_verbose) { const int printed_capacity = max_error_log_print_code; address printed[printed_capacity]; printed[0] = nullptr; @@ -929,7 +929,8 @@ void VMError::report(outputStream* st, bool _verbose) { printed_len++; } } else { - frame fr = os::fetch_frame_from_context(_context); + frame fr = _context ? os::fetch_frame_from_context(_context) + : os::current_frame(); while (printed_len < limit && fr.pc() != nullptr) { if (print_code(st, _thread, fr.pc(), fr.pc() == _pc, printed, printed_capacity)) { printed_len++; diff --git a/src/java.base/linux/classes/sun/nio/fs/LinuxDosFileAttributeView.java b/src/java.base/linux/classes/sun/nio/fs/LinuxDosFileAttributeView.java index a60f2ad45f995bfcb8f08adc98004e719912de13..70d701c1ef7bf08574c7633ec51968dfaae3bd5b 100644 --- a/src/java.base/linux/classes/sun/nio/fs/LinuxDosFileAttributeView.java +++ b/src/java.base/linux/classes/sun/nio/fs/LinuxDosFileAttributeView.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 @@ -182,7 +182,7 @@ class LinuxDosFileAttributeView x.rethrowAsIOException(file); return null; // keep compiler happy } finally { - close(fd); + close(fd, e -> null); } } @@ -277,7 +277,7 @@ class LinuxDosFileAttributeView } catch (UnixException x) { x.rethrowAsIOException(file); } finally { - close(fd); + close(fd, e -> null); } } } diff --git a/src/java.base/linux/classes/sun/nio/fs/LinuxWatchService.java b/src/java.base/linux/classes/sun/nio/fs/LinuxWatchService.java index 3e53b59ff906ae7110ff57f6ee2b3820c6dfdd0e..43719e0d5be26ea52a56fc261f52b8b66ede1309 100644 --- a/src/java.base/linux/classes/sun/nio/fs/LinuxWatchService.java +++ b/src/java.base/linux/classes/sun/nio/fs/LinuxWatchService.java @@ -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 @@ -70,7 +70,7 @@ class LinuxWatchService socketpair(sp); configureBlocking(sp[0], false); } catch (UnixException x) { - UnixNativeDispatcher.close(ifd); + UnixNativeDispatcher.close(ifd, e -> null); throw new IOException(x.errorString()); } @@ -296,9 +296,9 @@ class LinuxWatchService // free resources unsafe.freeMemory(address); - UnixNativeDispatcher.close(socketpair[0]); - UnixNativeDispatcher.close(socketpair[1]); - UnixNativeDispatcher.close(ifd); + UnixNativeDispatcher.close(socketpair[0], e -> null); + UnixNativeDispatcher.close(socketpair[1], e -> null); + UnixNativeDispatcher.close(ifd, e -> null); } /** diff --git a/src/java.base/share/classes/com/sun/crypto/provider/ChaCha20Cipher.java b/src/java.base/share/classes/com/sun/crypto/provider/ChaCha20Cipher.java index 8cb200876ac0d5348470a57478cdbd8fcfed0190..917921801cbcb9712c61ffe1cf91fef064c37c3d 100644 --- a/src/java.base/share/classes/com/sun/crypto/provider/ChaCha20Cipher.java +++ b/src/java.base/share/classes/com/sun/crypto/provider/ChaCha20Cipher.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 @@ -159,7 +159,7 @@ abstract class ChaCha20Cipher extends CipherSpi { * ciphers, but allow {@code NoPadding}. See JCE spec. * * @param padding The padding type. The only allowed value is - * {@code NoPadding} case insensitive). + * {@code NoPadding} case insensitive. * * @throws NoSuchPaddingException if a padding scheme besides * {@code NoPadding} is provided. @@ -393,7 +393,7 @@ abstract class ChaCha20Cipher extends CipherSpi { return; } - byte[] newNonce = null; + byte[] newNonce; switch (mode) { case MODE_NONE: throw new InvalidAlgorithmParameterException( @@ -420,12 +420,6 @@ abstract class ChaCha20Cipher extends CipherSpi { throw new RuntimeException("Invalid mode: " + mode); } - // If after all the above processing we still don't have a nonce value - // then supply a random one provided a random source has been given. - if (newNonce == null) { - newNonce = createRandomNonce(random); - } - // Continue with initialization init(opmode, key, newNonce); } diff --git a/src/java.base/share/classes/com/sun/crypto/provider/DHKeyAgreement.java b/src/java.base/share/classes/com/sun/crypto/provider/DHKeyAgreement.java index 94f41e614f17ce6be4caaffbd0b317ce7809c31a..01f978fff615ff0ae7f3dd84f8791536fcf99d5d 100644 --- a/src/java.base/share/classes/com/sun/crypto/provider/DHKeyAgreement.java +++ b/src/java.base/share/classes/com/sun/crypto/provider/DHKeyAgreement.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -344,6 +344,8 @@ extends KeyAgreementSpi { } else { // Array too short, pad it w/ leading 0s if (secret.length < expectedLen) { + Arrays.fill(sharedSecret, offset, + offset + (expectedLen - secret.length), (byte)0); System.arraycopy(secret, 0, sharedSecret, offset + (expectedLen - secret.length), secret.length); diff --git a/src/java.base/share/classes/com/sun/crypto/provider/SunJCE.java b/src/java.base/share/classes/com/sun/crypto/provider/SunJCE.java index a020e1c15d89ae22c72de3f2c2ab54e6f409b177..38836d2701eebe0e6b07c1798808a6de5be9563e 100644 --- a/src/java.base/share/classes/com/sun/crypto/provider/SunJCE.java +++ b/src/java.base/share/classes/com/sun/crypto/provider/SunJCE.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -525,8 +525,8 @@ public final class SunJCE extends Provider { ps("AlgorithmParameters", "RC2", "com.sun.crypto.provider.RC2Parameters"); - ps("AlgorithmParameters", "OAEP", - "com.sun.crypto.provider.OAEPParameters"); + psA("AlgorithmParameters", "OAEP", + "com.sun.crypto.provider.OAEPParameters", null); psA("AlgorithmParameters", "ChaCha20-Poly1305", "com.sun.crypto.provider.ChaCha20Poly1305Parameters", null); diff --git a/src/java.base/share/classes/java/io/File.java b/src/java.base/share/classes/java/io/File.java index 3f7cd86cf7027eaa3b126a06e37e75a4ca7db517..f279ee56bf516cf0d0f31259228e1b67ab7ca24b 100644 --- a/src/java.base/share/classes/java/io/File.java +++ b/src/java.base/share/classes/java/io/File.java @@ -2012,7 +2012,7 @@ public class File int prefixLength = prefix.length(); int nusLength = nus.length(); - int suffixLength = suffix.length();; + int suffixLength = suffix.length(); String name; int nameMax = fs.getNameMax(dir.getPath()); diff --git a/src/java.base/share/classes/java/io/InvalidClassException.java b/src/java.base/share/classes/java/io/InvalidClassException.java index 6de0e70f760fe88f7b7ce62886529d6fc7667318..be187597726a8356e0d31587946d1535864fd024 100644 --- a/src/java.base/share/classes/java/io/InvalidClassException.java +++ b/src/java.base/share/classes/java/io/InvalidClassException.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2022, Oracle and/or its affiliates. All rights reserved. * 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,9 +73,34 @@ public class InvalidClassException extends ObjectStreamException { classname = cname; } + /** + * Report an InvalidClassException for the reason and cause specified. + * + * @param reason String describing the reason for the exception. + * @param cause the cause + * @since 19 + */ + public InvalidClassException(String reason, Throwable cause) { + super(reason, cause); + } + + /** + * Report an InvalidClassException for the reason and cause specified. + * + * @param cname a String naming the invalid class. + * @param reason String describing the reason for the exception. + * @param cause the cause + * @since 19 + */ + public InvalidClassException(String cname, String reason, Throwable cause) { + super(reason, cause); + classname = cname; + } + /** * Produce the message and include the classname, if present. */ + @Override public String getMessage() { if (classname == null) return super.getMessage(); diff --git a/src/java.base/share/classes/java/io/InvalidObjectException.java b/src/java.base/share/classes/java/io/InvalidObjectException.java index c6e626b238facc87b905dbad6647ea5c081c58f0..a6331de45ab474ceb2f3906cb1a775cbea19ad1e 100644 --- a/src/java.base/share/classes/java/io/InvalidObjectException.java +++ b/src/java.base/share/classes/java/io/InvalidObjectException.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2022, Oracle and/or its affiliates. All rights reserved. * 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,21 @@ public class InvalidObjectException extends ObjectStreamException { * * @see ObjectInputValidation */ - public InvalidObjectException(String reason) { + public InvalidObjectException(String reason) { super(reason); } + + /** + * Constructs an {@code InvalidObjectException} with the given + * reason and cause. + * + * @param reason Detailed message explaining the reason for the failure. + * @param cause the cause + * + * @see ObjectInputValidation + * @since 19 + */ + public InvalidObjectException(String reason, Throwable cause) { + super(reason, cause); + } } diff --git a/src/java.base/share/classes/java/io/ObjectInputStream.java b/src/java.base/share/classes/java/io/ObjectInputStream.java index 714785cd117bf67ce0d057dfabdebbdb04152a00..14812fea9adda11a9c03b39f1a6d29dce9adf468 100644 --- a/src/java.base/share/classes/java/io/ObjectInputStream.java +++ b/src/java.base/share/classes/java/io/ObjectInputStream.java @@ -1429,9 +1429,7 @@ public class ObjectInputStream event.commit(); } if (serialFilter != null && (status == null || status == ObjectInputFilter.Status.REJECTED)) { - InvalidClassException ice = new InvalidClassException("filter status: " + status); - ice.initCause(ex); - throw ice; + throw new InvalidClassException("filter status: " + status, ex); } } @@ -1996,14 +1994,10 @@ public class ObjectInputStream } catch (ClassNotFoundException ex) { resolveEx = ex; } catch (IllegalAccessError aie) { - IOException ice = new InvalidClassException(aie.getMessage()); - ice.initCause(aie); - throw ice; + throw new InvalidClassException(aie.getMessage(), aie); } catch (OutOfMemoryError memerr) { - IOException ex = new InvalidObjectException("Proxy interface limit exceeded: " + - Arrays.toString(ifaces)); - ex.initCause(memerr); - throw ex; + throw new InvalidObjectException("Proxy interface limit exceeded: " + + Arrays.toString(ifaces), memerr); } // Call filterCheck on the class before reading anything else @@ -2016,10 +2010,8 @@ public class ObjectInputStream depth++; desc.initProxy(cl, resolveEx, readClassDesc(false)); } catch (OutOfMemoryError memerr) { - IOException ex = new InvalidObjectException("Proxy interface limit exceeded: " + - Arrays.toString(ifaces)); - ex.initCause(memerr); - throw ex; + throw new InvalidObjectException("Proxy interface limit exceeded: " + + Arrays.toString(ifaces), memerr); } finally { depth--; } @@ -2050,8 +2042,8 @@ public class ObjectInputStream try { readDesc = readClassDescriptor(); } catch (ClassNotFoundException ex) { - throw (IOException) new InvalidClassException( - "failed to read class descriptor").initCause(ex); + throw new InvalidClassException("failed to read class descriptor", + ex); } Class cl = null; @@ -2221,9 +2213,8 @@ public class ObjectInputStream Enum en = Enum.valueOf((Class)cl, name); result = en; } catch (IllegalArgumentException ex) { - throw (IOException) new InvalidObjectException( - "enum constant " + name + " does not exist in " + - cl).initCause(ex); + throw new InvalidObjectException("enum constant " + + name + " does not exist in " + cl, ex); } if (!unshared) { handles.setObject(enumHandle, result); @@ -2262,9 +2253,8 @@ public class ObjectInputStream try { obj = desc.isInstantiable() ? desc.newInstance() : null; } catch (Exception ex) { - throw (IOException) new InvalidClassException( - desc.forClass().getName(), - "unable to create instance").initCause(ex); + throw new InvalidClassException(desc.forClass().getName(), + "unable to create instance", ex); } passHandle = handles.assign(unshared ? unsharedMarker : obj); @@ -2388,16 +2378,12 @@ public class ObjectInputStream try { return (Object) ctrMH.invokeExact(fieldValues.primValues, fieldValues.objValues); } catch (Exception e) { - InvalidObjectException ioe = new InvalidObjectException(e.getMessage()); - ioe.initCause(e); - throw ioe; + throw new InvalidObjectException(e.getMessage(), e); } catch (Error e) { throw e; } catch (Throwable t) { - ObjectStreamException ose = new InvalidObjectException( - "ReflectiveOperationException during deserialization"); - ose.initCause(t); - throw ose; + throw new InvalidObjectException("ReflectiveOperationException " + + "during deserialization", t); } } diff --git a/src/java.base/share/classes/java/io/ObjectStreamClass.java b/src/java.base/share/classes/java/io/ObjectStreamClass.java index 86ed2b839d13727791114e7cc6f816147243bc97..c41e8b1744a088c8377eb0decab9d9a11c3acb8b 100644 --- a/src/java.base/share/classes/java/io/ObjectStreamClass.java +++ b/src/java.base/share/classes/java/io/ObjectStreamClass.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -709,8 +709,9 @@ public class ObjectStreamClass implements Serializable { try { fields[i] = new ObjectStreamField(fname, signature, false); } catch (RuntimeException e) { - throw (IOException) new InvalidClassException(name, - "invalid descriptor for field " + fname).initCause(e); + throw new InvalidClassException(name, + "invalid descriptor for field " + + fname, e); } } computeFieldOffsets(); diff --git a/src/java.base/share/classes/java/io/ObjectStreamException.java b/src/java.base/share/classes/java/io/ObjectStreamException.java index 779cc0627d3312882ce02c95467face69861a9c9..a7d19cdc1fa6302f3ffa04184f7035ffd31729c2 100644 --- a/src/java.base/share/classes/java/io/ObjectStreamException.java +++ b/src/java.base/share/classes/java/io/ObjectStreamException.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2022, Oracle and/or its affiliates. All rights reserved. * 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,10 +44,32 @@ public abstract class ObjectStreamException extends IOException { super(message); } + /** + * Create an ObjectStreamException with the specified message and + * cause. + * + * @param message the detailed message for the exception + * @param cause the cause + * @since 19 + */ + protected ObjectStreamException(String message, Throwable cause) { + super(message, cause); + } + /** * Create an ObjectStreamException. */ protected ObjectStreamException() { super(); } + + /** + * Create an ObjectStreamException with the specified cause. + * + * @param cause the cause + * @since 19 + */ + protected ObjectStreamException(Throwable cause) { + super(cause); + } } diff --git a/src/java.base/share/classes/java/io/PrintStream.java b/src/java.base/share/classes/java/io/PrintStream.java index 0281ed66ca82e08991faf7f33ea97ab589e17795..d18afa97d540f575cb790ed317aeb9cc2713daf4 100644 --- a/src/java.base/share/classes/java/io/PrintStream.java +++ b/src/java.base/share/classes/java/io/PrintStream.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -464,22 +464,11 @@ public class PrintStream extends FilterOutputStream } /** - * Flushes the stream and checks its error state. The internal error state - * is set to {@code true} when the underlying output stream throws an - * {@code IOException} other than {@code InterruptedIOException}, - * and when the {@code setError} method is invoked. If an operation - * on the underlying output stream throws an - * {@code InterruptedIOException}, then the {@code PrintStream} - * converts the exception back into an interrupt by doing: - *
    {@code
    -     *     Thread.currentThread().interrupt();
    -     * }
    - * or the equivalent. + * Flushes the stream if it's not closed and checks its error state. * * @return {@code true} if and only if this stream has encountered an - * {@code IOException} other than - * {@code InterruptedIOException}, or the - * {@code setError} method has been invoked + * {@code IOException}, or the {@code setError} method has been + * invoked */ public boolean checkError() { if (out != null) @@ -504,7 +493,7 @@ public class PrintStream extends FilterOutputStream } /** - * Clears the internal error state of this stream. + * Clears the error state of this stream. * *

    This method will cause subsequent invocations of {@link * #checkError()} to return {@code false} until another write diff --git a/src/java.base/share/classes/java/io/PrintWriter.java b/src/java.base/share/classes/java/io/PrintWriter.java index 874a03cce3bbfbd7e83afeb72fe8a75ba548f50b..249efc4d99a1297dfb4b47fe7fcbfa5648ef1cdd 100644 --- a/src/java.base/share/classes/java/io/PrintWriter.java +++ b/src/java.base/share/classes/java/io/PrintWriter.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -428,9 +428,9 @@ public class PrintWriter extends Writer { /** * Flushes the stream if it's not closed and checks its error state. * - * @return {@code true} if the print stream has encountered an error, - * either on the underlying output stream or during a format - * conversion. + * @return {@code true} if and only if this stream has encountered an + * {@code IOException}, or the {@code setError} method has been + * invoked */ public boolean checkError() { if (out != null) { @@ -445,7 +445,7 @@ public class PrintWriter extends Writer { } /** - * Indicates that an error has occurred. + * Sets the error state of the stream to {@code true}. * *

    This method will cause subsequent invocations of {@link * #checkError()} to return {@code true} until {@link diff --git a/src/java.base/share/classes/java/io/package-info.java b/src/java.base/share/classes/java/io/package-info.java index 1c41f9835e6fc5959ea8f2c8bb07653bda3d7bf4..81f61412eedc50a606582d98fffcc04fc07e884e 100644 --- a/src/java.base/share/classes/java/io/package-info.java +++ b/src/java.base/share/classes/java/io/package-info.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2017, 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 @@ -27,10 +27,14 @@ * Provides for system input and output through data streams, * serialization and the file system. * - * Unless otherwise noted, passing a null argument to a constructor or + * Unless otherwise noted, passing a {@code null} argument to a constructor or * method in any class or interface in this package will cause a * {@code NullPointerException} to be thrown. * + * A pathname string passed as a {@code String} argument to a + * constructor or method in any class or interface in this package will be + * interpreted as described in the class specification of {@link File}. + * *

    Object Serialization

    *

    Warning: Deserialization of untrusted data is inherently dangerous * and should be avoided. Untrusted data should be carefully validated according to the diff --git a/src/java.base/share/classes/java/lang/AbstractStringBuilder.java b/src/java.base/share/classes/java/lang/AbstractStringBuilder.java index cf83c825d38f2761d09d6ad7ada7091d7273639c..fed3a6f9178c00a224a199c0e8ec6b5a8d6c36ed 100644 --- a/src/java.base/share/classes/java/lang/AbstractStringBuilder.java +++ b/src/java.base/share/classes/java/lang/AbstractStringBuilder.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 @@ -56,7 +56,8 @@ import static java.lang.String.checkOffset; * @author Ulf Zibis * @since 1.5 */ -abstract class AbstractStringBuilder implements Appendable, CharSequence { +abstract sealed class AbstractStringBuilder implements Appendable, CharSequence + permits StringBuilder, StringBuffer { /** * The value is used for character storage. */ diff --git a/src/java.base/share/classes/java/lang/Character.java b/src/java.base/share/classes/java/lang/Character.java index 92e9b5b43f5688cf3bb9efa575a5de47f8f74fd7..d30743b143cb830637aa238df7f19e858cff7a20 100644 --- a/src/java.base/share/classes/java/lang/Character.java +++ b/src/java.base/share/classes/java/lang/Character.java @@ -737,10 +737,13 @@ class Character implements java.io.Serializable, Comparable, Constabl */ public static final class UnicodeBlock extends Subset { /** - * 696 - the expected number of entities + * NUM_ENTITIES should match the total number of UnicodeBlocks + * to calculate the initial capacity of the map. It should be + * adjusted whenever the Unicode Character Database is upgraded. + * * 0.75 - the default load factor of HashMap */ - private static final int NUM_ENTITIES = 696; + private static final int NUM_ENTITIES = 737; private static Map map = new HashMap<>((int)(NUM_ENTITIES / 0.75f + 1.0f)); diff --git a/make/data/characterdata/CharacterData00.java.template b/src/java.base/share/classes/java/lang/CharacterData00.java.template similarity index 100% rename from make/data/characterdata/CharacterData00.java.template rename to src/java.base/share/classes/java/lang/CharacterData00.java.template diff --git a/make/data/characterdata/CharacterData01.java.template b/src/java.base/share/classes/java/lang/CharacterData01.java.template similarity index 100% rename from make/data/characterdata/CharacterData01.java.template rename to src/java.base/share/classes/java/lang/CharacterData01.java.template diff --git a/make/data/characterdata/CharacterData02.java.template b/src/java.base/share/classes/java/lang/CharacterData02.java.template similarity index 100% rename from make/data/characterdata/CharacterData02.java.template rename to src/java.base/share/classes/java/lang/CharacterData02.java.template diff --git a/make/data/characterdata/CharacterData03.java.template b/src/java.base/share/classes/java/lang/CharacterData03.java.template similarity index 100% rename from make/data/characterdata/CharacterData03.java.template rename to src/java.base/share/classes/java/lang/CharacterData03.java.template diff --git a/make/data/characterdata/CharacterData0E.java.template b/src/java.base/share/classes/java/lang/CharacterData0E.java.template similarity index 100% rename from make/data/characterdata/CharacterData0E.java.template rename to src/java.base/share/classes/java/lang/CharacterData0E.java.template diff --git a/make/data/characterdata/CharacterDataLatin1.java.template b/src/java.base/share/classes/java/lang/CharacterDataLatin1.java.template similarity index 100% rename from make/data/characterdata/CharacterDataLatin1.java.template rename to src/java.base/share/classes/java/lang/CharacterDataLatin1.java.template diff --git a/src/java.base/share/classes/java/lang/Math.java b/src/java.base/share/classes/java/lang/Math.java index 7341aa56a6ac870f6d05dfbac3adca52675f58c5..6d8fa48c9764e6207e2aa0dac074abad72b15ef4 100644 --- a/src/java.base/share/classes/java/lang/Math.java +++ b/src/java.base/share/classes/java/lang/Math.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1994, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1994, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -131,14 +131,27 @@ public final class Math { * The {@code double} value that is closer than any other to * e, the base of the natural logarithms. */ - public static final double E = 2.7182818284590452354; + public static final double E = 2.718281828459045; /** * The {@code double} value that is closer than any other to - * pi, the ratio of the circumference of a circle to its - * diameter. + * pi (π), the ratio of the circumference of a circle to + * its diameter. */ - public static final double PI = 3.14159265358979323846; + public static final double PI = 3.141592653589793; + + /** + * The {@code double} value that is closer than any other to + * tau (τ), the ratio of the circumference of a circle + * to its radius. + * + * @apiNote + * The value of pi is one half that of tau; in other + * words, tau is double pi . + * + * @since 19 + */ + public static final double TAU = 2.0 * PI; /** * Constant by which to multiply an angular value in degrees to obtain an diff --git a/src/java.base/share/classes/java/lang/StrictMath.java b/src/java.base/share/classes/java/lang/StrictMath.java index 53b25fedebbff2170d53c65ae8bb8e1015f7ab40..b551288a38f0194579d7ac0ab5621f42789b9d32 100644 --- a/src/java.base/share/classes/java/lang/StrictMath.java +++ b/src/java.base/share/classes/java/lang/StrictMath.java @@ -92,14 +92,27 @@ public final class StrictMath { * The {@code double} value that is closer than any other to * e, the base of the natural logarithms. */ - public static final double E = 2.7182818284590452354; + public static final double E = 2.718281828459045; /** * The {@code double} value that is closer than any other to - * pi, the ratio of the circumference of a circle to its + * pi (π), the ratio of the circumference of a circle to its * diameter. */ - public static final double PI = 3.14159265358979323846; + public static final double PI = 3.141592653589793; + + /** + * The {@code double} value that is closer than any other to + * tau (τ), the ratio of the circumference of a circle + * to its radius. + * + * @apiNote + * The value of pi is one half that of tau; in other + * words, tau is double pi . + * + * @since 19 + */ + public static final double TAU = 2.0 * PI; /** * Returns the trigonometric sine of an angle. Special cases: diff --git a/src/java.base/share/classes/java/lang/String.java b/src/java.base/share/classes/java/lang/String.java index e79884bd4cc62d1d98d43bc05f7b074a18d4519b..009a61a9ba39518832cec7545f1965a417c5e26a 100644 --- a/src/java.base/share/classes/java/lang/String.java +++ b/src/java.base/share/classes/java/lang/String.java @@ -525,56 +525,63 @@ public final class String this.value = "".value; this.coder = "".coder; } else if (charset == UTF_8.INSTANCE) { - if (COMPACT_STRINGS && !StringCoding.hasNegatives(bytes, offset, length)) { - this.value = Arrays.copyOfRange(bytes, offset, offset + length); - this.coder = LATIN1; - } else { + if (COMPACT_STRINGS) { + int dp = StringCoding.countPositives(bytes, offset, length); + if (dp == length) { + this.value = Arrays.copyOfRange(bytes, offset, offset + length); + this.coder = LATIN1; + return; + } int sl = offset + length; - int dp = 0; - byte[] dst = null; - if (COMPACT_STRINGS) { - dst = new byte[length]; - while (offset < sl) { - int b1 = bytes[offset]; - if (b1 >= 0) { - dst[dp++] = (byte)b1; + byte[] dst = new byte[length]; + if (dp > 0) { + System.arraycopy(bytes, offset, dst, 0, dp); + offset += dp; + } + while (offset < sl) { + int b1 = bytes[offset++]; + if (b1 >= 0) { + dst[dp++] = (byte)b1; + continue; + } + if ((b1 & 0xfe) == 0xc2 && offset < sl) { // b1 either 0xc2 or 0xc3 + int b2 = bytes[offset]; + if (b2 < -64) { // continuation bytes are always negative values in the range -128 to -65 + dst[dp++] = (byte)decode2(b1, b2); offset++; continue; } - if ((b1 & 0xfe) == 0xc2 && offset + 1 < sl) { // b1 either 0xc2 or 0xc3 - int b2 = bytes[offset + 1]; - if (!isNotContinuation(b2)) { - dst[dp++] = (byte)decode2(b1, b2); - offset += 2; - continue; - } - } - // anything not a latin1, including the repl - // we have to go with the utf16 - break; - } - if (offset == sl) { - if (dp != dst.length) { - dst = Arrays.copyOf(dst, dp); - } - this.value = dst; - this.coder = LATIN1; - return; } + // anything not a latin1, including the REPL + // we have to go with the utf16 + offset--; + break; } - if (dp == 0 || dst == null) { - dst = new byte[length << 1]; - } else { - byte[] buf = new byte[length << 1]; - StringLatin1.inflate(dst, 0, buf, 0, dp); - dst = buf; + if (offset == sl) { + if (dp != dst.length) { + dst = Arrays.copyOf(dst, dp); + } + this.value = dst; + this.coder = LATIN1; + return; } + byte[] buf = new byte[length << 1]; + StringLatin1.inflate(dst, 0, buf, 0, dp); + dst = buf; dp = decodeUTF8_UTF16(bytes, offset, sl, dst, dp, true); if (dp != length) { dst = Arrays.copyOf(dst, dp << 1); } this.value = dst; this.coder = UTF16; + } else { // !COMPACT_STRINGS + byte[] dst = new byte[length << 1]; + int dp = decodeUTF8_UTF16(bytes, offset, offset + length, dst, 0, true); + if (dp != length) { + dst = Arrays.copyOf(dst, dp << 1); + } + this.value = dst; + this.coder = UTF16; } } else if (charset == ISO_8859_1.INSTANCE) { if (COMPACT_STRINGS) { @@ -682,41 +689,43 @@ public final class String if (length == 0) { return ""; } - if (COMPACT_STRINGS && !StringCoding.hasNegatives(bytes, offset, length)) { - return new String(Arrays.copyOfRange(bytes, offset, offset + length), LATIN1); - } else { + int dp; + byte[] dst; + if (COMPACT_STRINGS) { + dp = StringCoding.countPositives(bytes, offset, length); int sl = offset + length; - int dp = 0; - byte[] dst = null; - if (COMPACT_STRINGS) { - dst = new byte[length]; - while (offset < sl) { - int b1 = bytes[offset]; - if (b1 >= 0) { - dst[dp++] = (byte) b1; + if (dp == length) { + return new String(Arrays.copyOfRange(bytes, offset, offset + length), LATIN1); + } + dst = new byte[length]; + System.arraycopy(bytes, offset, dst, 0, dp); + offset += dp; + while (offset < sl) { + int b1 = bytes[offset++]; + if (b1 >= 0) { + dst[dp++] = (byte)b1; + continue; + } + if ((b1 & 0xfe) == 0xc2 && offset < sl) { // b1 either 0xc2 or 0xc3 + int b2 = bytes[offset]; + if (b2 < -64) { // continuation bytes are always negative values in the range -128 to -65 + dst[dp++] = (byte)decode2(b1, b2); offset++; continue; } - if ((b1 & 0xfe) == 0xc2 && offset + 1 < sl) { // b1 either 0xc2 or 0xc3 - int b2 = bytes[offset + 1]; - if (!isNotContinuation(b2)) { - dst[dp++] = (byte) decode2(b1, b2); - offset += 2; - continue; - } - } - // anything not a latin1, including the REPL - // we have to go with the utf16 - break; } - if (offset == sl) { - if (dp != dst.length) { - dst = Arrays.copyOf(dst, dp); - } - return new String(dst, LATIN1); + // anything not a latin1, including the REPL + // we have to go with the utf16 + offset--; + break; + } + if (offset == sl) { + if (dp != dst.length) { + dst = Arrays.copyOf(dst, dp); } + return new String(dst, LATIN1); } - if (dp == 0 || dst == null) { + if (dp == 0) { dst = new byte[length << 1]; } else { byte[] buf = new byte[length << 1]; @@ -724,11 +733,14 @@ public final class String dst = buf; } dp = decodeUTF8_UTF16(bytes, offset, sl, dst, dp, false); - if (dp != length) { - dst = Arrays.copyOf(dst, dp << 1); - } - return new String(dst, UTF16); + } else { // !COMPACT_STRINGS + dst = new byte[length << 1]; + dp = decodeUTF8_UTF16(bytes, offset, offset + length, dst, 0, false); + } + if (dp != length) { + dst = Arrays.copyOf(dst, dp << 1); } + return new String(dst, UTF16); } static String newStringNoRepl(byte[] src, Charset cs) throws CharacterCodingException { @@ -1019,17 +1031,15 @@ public final class String */ /* package-private */ static int decodeASCII(byte[] sa, int sp, char[] da, int dp, int len) { - if (!StringCoding.hasNegatives(sa, sp, len)) { - StringLatin1.inflate(sa, sp, da, dp, len); - return len; - } else { - int start = sp; - int end = sp + len; - while (sp < end && sa[sp] >= 0) { - da[dp++] = (char) sa[sp++]; + int count = StringCoding.countPositives(sa, sp, len); + while (count < len) { + if (sa[sp + count] < 0) { + break; } - return sp - start; + count++; } + StringLatin1.inflate(sa, sp, da, dp, count); + return count; } private static boolean isNotContinuation(int b) { diff --git a/src/java.base/share/classes/java/lang/StringCoding.java b/src/java.base/share/classes/java/lang/StringCoding.java index ec81c3795799f1f91a41d3c373053007e8b565cc..293fbdb78dc85c6a272c4ffef9340944b83b41fb 100644 --- a/src/java.base/share/classes/java/lang/StringCoding.java +++ b/src/java.base/share/classes/java/lang/StringCoding.java @@ -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 @@ -34,14 +34,27 @@ class StringCoding { private StringCoding() { } - @IntrinsicCandidate public static boolean hasNegatives(byte[] ba, int off, int len) { - for (int i = off; i < off + len; i++) { + return countPositives(ba, off, len) != len; + } + + /** + * Count the number of leading positive bytes in the range. + * + * @implSpec the implementation must return len if there are no negative + * bytes in the range. If there are negative bytes, the implementation must return + * a value that is less than or equal to the index of the first negative byte + * in the range. + */ + @IntrinsicCandidate + public static int countPositives(byte[] ba, int off, int len) { + int limit = off + len; + for (int i = off; i < limit; i++) { if (ba[i] < 0) { - return true; + return i - off; } } - return false; + return len; } @IntrinsicCandidate diff --git a/src/java.base/share/classes/java/lang/StringConcatHelper.java b/src/java.base/share/classes/java/lang/StringConcatHelper.java index f267fd9e1d6d9eb4e81b30b4cecaf295ba648f04..3867c10e8d6fcdead85bdc9b4f6d81dd31bd8177 100644 --- a/src/java.base/share/classes/java/lang/StringConcatHelper.java +++ b/src/java.base/share/classes/java/lang/StringConcatHelper.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2020, 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 @@ -430,7 +430,7 @@ final class StringConcatHelper { * Produce a String from a concatenation of single argument, which we * end up using for trivial concatenations like {@code "" + arg}. * - * This will always create a new Object to comply with JLS 15.18.1: + * This will always create a new Object to comply with JLS {@jls 15.18.1}: * "The String object is newly created unless the expression is a * compile-time constant expression". * diff --git a/src/java.base/share/classes/java/lang/annotation/ElementType.java b/src/java.base/share/classes/java/lang/annotation/ElementType.java index c046272b12c7b12d1ef75bd3b305b7269b4c1695..97275fb97ec8b6fe31d1293727f169075f106045 100644 --- a/src/java.base/share/classes/java/lang/annotation/ElementType.java +++ b/src/java.base/share/classes/java/lang/annotation/ElementType.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 @@ -40,14 +40,14 @@ package java.lang.annotation; *

    The constants {@link #ANNOTATION_TYPE}, {@link #CONSTRUCTOR}, {@link * #FIELD}, {@link #LOCAL_VARIABLE}, {@link #METHOD}, {@link #PACKAGE}, {@link * #MODULE}, {@link #PARAMETER}, {@link #TYPE}, and {@link #TYPE_PARAMETER} - * correspond to the declaration contexts in JLS 9.6.4.1. + * correspond to the declaration contexts in JLS {@jls 9.6.4.1}. * *

    For example, an annotation whose interface is meta-annotated with * {@code @Target(ElementType.FIELD)} may only be written as a modifier for a * field declaration. * *

    The constant {@link #TYPE_USE} corresponds to the type contexts in JLS - * 4.11, as well as to two declaration contexts: class and interface + * {@jls 4.11}, as well as to two declaration contexts: class and interface * declarations (including annotation declarations) and type parameter * declarations. * diff --git a/src/java.base/share/classes/java/lang/constant/ClassDesc.java b/src/java.base/share/classes/java/lang/constant/ClassDesc.java index 14923594c0e1bc24cbfbce13bc91596dcd0495ac..6742b622a40c998a38ee52228622b95befb18205 100644 --- a/src/java.base/share/classes/java/lang/constant/ClassDesc.java +++ b/src/java.base/share/classes/java/lang/constant/ClassDesc.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 @@ -116,7 +116,7 @@ public sealed interface ClassDesc * followed by the field descriptor for the component type. Examples of * valid type descriptor strings include {@code "Ljava/lang/String;"}, {@code "I"}, * {@code "[I"}, {@code "V"}, {@code "[Ljava/lang/String;"}, etc. - * See JVMS 4.3.2 ("Field Descriptors") for more detail. + * See JVMS {@jvms 4.3.2 }("Field Descriptors") for more detail. * * @param descriptor a field descriptor string * @return a {@linkplain ClassDesc} describing the desired class @@ -148,7 +148,8 @@ public sealed interface ClassDesc * is described by this {@linkplain ClassDesc}. * * @return a {@linkplain ClassDesc} describing the array type - * @throws IllegalStateException if the resulting {@linkplain ClassDesc} would have an array rank of greater than 255 + * @throws IllegalStateException if the resulting {@linkplain + * ClassDesc} would have an array rank of greater than 255 * @jvms 4.4.1 The CONSTANT_Class_info Structure */ default ClassDesc arrayType() { @@ -167,14 +168,27 @@ public sealed interface ClassDesc * * @param rank the rank of the array * @return a {@linkplain ClassDesc} describing the array type - * @throws IllegalArgumentException if the rank is less than or equal to zero or if the rank of the resulting array type is + * @throws IllegalArgumentException if the rank is less than or + * equal to zero or if the rank of the resulting array type is * greater than 255 * @jvms 4.4.1 The CONSTANT_Class_info Structure */ default ClassDesc arrayType(int rank) { - int currentDepth = ConstantUtils.arrayDepth(descriptorString()); - if (rank <= 0 || currentDepth + rank > ConstantUtils.MAX_ARRAY_TYPE_DESC_DIMENSIONS) - throw new IllegalArgumentException("rank: " + currentDepth + rank); + int netRank; + if (rank <= 0) { + throw new IllegalArgumentException("rank " + rank + " is not a positive value"); + } + try { + int currentDepth = ConstantUtils.arrayDepth(descriptorString()); + netRank = Math.addExact(currentDepth, rank); + if (netRank > ConstantUtils.MAX_ARRAY_TYPE_DESC_DIMENSIONS) { + throw new IllegalArgumentException("rank: " + netRank + + " exceeds maximum supported dimension of " + + ConstantUtils.MAX_ARRAY_TYPE_DESC_DIMENSIONS); + } + } catch (ArithmeticException ae) { + throw new IllegalArgumentException("Integer overflow in rank computation"); + } return ClassDesc.ofDescriptor("[".repeat(rank) + descriptorString()); } diff --git a/src/java.base/share/classes/java/lang/constant/Constable.java b/src/java.base/share/classes/java/lang/constant/Constable.java index 33875654c05404d7e1fb8eeb96844626b9d235d7..e404dff6e4ba8a89ad035f89f1e88a71b816f8fb 100644 --- a/src/java.base/share/classes/java/lang/constant/Constable.java +++ b/src/java.base/share/classes/java/lang/constant/Constable.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 @@ -32,7 +32,7 @@ import java.util.Optional; /** * Represents a type which is constable. A constable type is one whose * values are constants that can be represented in the constant pool of a Java - * classfile as described in JVMS 4.4, and whose instances can describe themselves + * classfile as described in JVMS {@jvms 4.4}, and whose instances can describe themselves * nominally as a {@link ConstantDesc}. * *

    Some constable types have a native representation in the constant pool: @@ -48,7 +48,7 @@ import java.util.Optional; * Platform API are types that support Java language features such as {@link Enum}, * and runtime support classes such as {@link VarHandle}. These are typically * described with a {@link DynamicConstantDesc}, which describes dynamically - * generated constants (JVMS 4.4.10). + * generated constants (JVMS {@jvms 4.4.10}). * *

    The nominal form of an instance of a constable type is obtained via * {@link #describeConstable()}. A {@linkplain Constable} need diff --git a/src/java.base/share/classes/java/lang/constant/ConstantDesc.java b/src/java.base/share/classes/java/lang/constant/ConstantDesc.java index 70c5f8fcb558be811518d5c5b0b94249e2501ad4..401119989a9527b2a49542157d831ad79377b4bc 100644 --- a/src/java.base/share/classes/java/lang/constant/ConstantDesc.java +++ b/src/java.base/share/classes/java/lang/constant/ConstantDesc.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 @@ -32,7 +32,7 @@ import java.lang.invoke.VarHandle.VarHandleDesc; /** * A nominal descriptor for a loadable - * constant value, as defined in JVMS 4.4. Such a descriptor can be resolved via + * constant value, as defined in JVMS {@jvms 4.4}. Such a descriptor can be resolved via * {@link ConstantDesc#resolveConstantDesc(MethodHandles.Lookup)} to yield the * constant value itself. * @@ -87,7 +87,7 @@ public sealed interface ConstantDesc String { /** * Resolves this descriptor reflectively, emulating the resolution behavior - * of JVMS 5.4.3 and the access control behavior of JVMS 5.4.4. The resolution + * of JVMS {@jvms 5.4.3} and the access control behavior of JVMS {@jvms 5.4.4}. The resolution * and access control context is provided by the {@link MethodHandles.Lookup} * parameter. No caching of the resulting value is performed. * diff --git a/src/java.base/share/classes/java/lang/constant/package-info.java b/src/java.base/share/classes/java/lang/constant/package-info.java index 9bc978e44a192e0415d550f16d1a50cf7acfe565..fd85dfb93d74290ceb126d730856b5111d00bb46 100644 --- a/src/java.base/share/classes/java/lang/constant/package-info.java +++ b/src/java.base/share/classes/java/lang/constant/package-info.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 @@ -55,7 +55,7 @@ * referenced in their nominal description are present and accessible. * *

    The subtypes of {@link java.lang.constant.ConstantDesc} describe various kinds - * of constant values. For each type of loadable constant pool entry defined in JVMS 4.4, + * of constant values. For each type of loadable constant pool entry defined in JVMS {@jvms 4.4}, * there is a corresponding subtype of {@link java.lang.constant.ConstantDesc}: * {@link java.lang.constant.ClassDesc}, {@link java.lang.constant.MethodTypeDesc}, * {@link java.lang.constant.DirectMethodHandleDesc}, {@link java.lang.String}, diff --git a/src/java.base/share/classes/java/lang/invoke/CallSite.java b/src/java.base/share/classes/java/lang/invoke/CallSite.java index e159e235f30a30830bd263952566974d8bc61c91..ec002e1fc460aa4d4bf5ef378f14f608c1cde76a 100644 --- a/src/java.base/share/classes/java/lang/invoke/CallSite.java +++ b/src/java.base/share/classes/java/lang/invoke/CallSite.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2021, 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 @@ -40,9 +40,9 @@ import jdk.internal.vm.annotation.Stable; * In any case, it may be invoked through an associated method handle * called its {@linkplain #dynamicInvoker dynamic invoker}. *

    - * {@code CallSite} is an abstract class which does not allow + * {@code CallSite} is an abstract sealed class which does not allow * direct subclassing by users. It has three immediate, - * concrete subclasses that may be either instantiated or subclassed. + * concrete non-sealed subclasses that may be either instantiated or subclassed. *

      *
    • If a mutable target is not required, an {@code invokedynamic} instruction * may be permanently bound by means of a {@linkplain ConstantCallSite constant call site}. @@ -85,7 +85,7 @@ private static CallSite bootstrapDynamic(MethodHandles.Lookup caller, String nam * @since 1.7 */ public -abstract class CallSite { +abstract sealed class CallSite permits ConstantCallSite, MutableCallSite, VolatileCallSite { // The actual payload of this call site. // Can be modified using {@link MethodHandleNatives#setCallSiteTargetNormal} or {@link MethodHandleNatives#setCallSiteTargetVolatile}. diff --git a/src/java.base/share/classes/java/lang/invoke/ConstantBootstraps.java b/src/java.base/share/classes/java/lang/invoke/ConstantBootstraps.java index 27d74284dc6d4361fd0f27a452332fa2d569a41b..b3858104e21e4cac947671dd26ff90c0dfd84114 100644 --- a/src/java.base/share/classes/java/lang/invoke/ConstantBootstraps.java +++ b/src/java.base/share/classes/java/lang/invoke/ConstantBootstraps.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 @@ -96,7 +96,7 @@ public final class ConstantBootstraps { * descriptor is specified by {@code name}. * * @param lookup unused - * @param name the descriptor (JVMS 4.3) of the desired primitive type + * @param name the descriptor (JVMS {@jvms 4.3}) of the desired primitive type * @param type the required result type (must be {@code Class.class}) * @return the {@link Class} mirror * @throws IllegalArgumentException if the name is not a descriptor for a diff --git a/src/java.base/share/classes/java/lang/invoke/ConstantCallSite.java b/src/java.base/share/classes/java/lang/invoke/ConstantCallSite.java index e2e3f478a3c864af83d5218218df0fc36cff490e..29e557ad141b2065f33c67bd5c5a0ab058417f7c 100644 --- a/src/java.base/share/classes/java/lang/invoke/ConstantCallSite.java +++ b/src/java.base/share/classes/java/lang/invoke/ConstantCallSite.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2013, 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 @@ -35,7 +35,7 @@ import jdk.internal.vm.annotation.Stable; * @author John Rose, JSR 292 EG * @since 1.7 */ -public class ConstantCallSite extends CallSite { +public non-sealed class ConstantCallSite extends CallSite { private static final Unsafe UNSAFE = Unsafe.getUnsafe(); @Stable // should NOT be constant folded during instance initialization (isFrozen == false) diff --git a/src/java.base/share/classes/java/lang/invoke/MethodHandle.java b/src/java.base/share/classes/java/lang/invoke/MethodHandle.java index ec910dbf8fe34598c1ba9ec0b9eebf7bab2daabb..fb7ef0afbac3f9be8d74e24880bc6ea621cc7368 100644 --- a/src/java.base/share/classes/java/lang/invoke/MethodHandle.java +++ b/src/java.base/share/classes/java/lang/invoke/MethodHandle.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2021, 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 @@ -807,15 +807,15 @@ public abstract class MethodHandle implements Constable { * (The types do not need to be related in any particular way. * This is because a dynamic value of null can convert to any reference type.) *
    • If T0 and T1 are primitives, then a Java method invocation - * conversion (JLS 5.3) is applied, if one exists. + * conversion (JLS {@jls 5.3}) is applied, if one exists. * (Specifically, T0 must convert to T1 by a widening primitive conversion.) *
    • If T0 is a primitive and T1 a reference, - * a Java casting conversion (JLS 5.5) is applied if one exists. + * a Java casting conversion (JLS {@jls 5.5}) is applied if one exists. * (Specifically, the value is boxed from T0 to its wrapper class, * which is then widened as needed to T1.) *
    • If T0 is a reference and T1 a primitive, an unboxing * conversion will be applied at runtime, possibly followed - * by a Java method invocation conversion (JLS 5.3) + * by a Java method invocation conversion (JLS {@jls 5.3}) * on the primitive value. (These are the primitive widening conversions.) * T0 must be a wrapper class or a supertype of one. * (In the case where T0 is Object, these are the conversions diff --git a/src/java.base/share/classes/java/lang/invoke/MethodHandles.java b/src/java.base/share/classes/java/lang/invoke/MethodHandles.java index bdc2675099220d66b348734a239b97d22d5b98ec..7488db060d23521cf6b1072d117af1d564018b8f 100644 --- a/src/java.base/share/classes/java/lang/invoke/MethodHandles.java +++ b/src/java.base/share/classes/java/lang/invoke/MethodHandles.java @@ -1884,7 +1884,7 @@ public class MethodHandles { * as a normal class or interface has with its own defining loader. * This means that the hidden class may be unloaded if and only if * its defining loader is not reachable and thus may be reclaimed - * by a garbage collector (JLS 12.7). + * by a garbage collector (JLS {@jls 12.7}). * *

      By default, a hidden class or interface may be unloaded * even if the class loader that is marked as its defining loader is @@ -2024,7 +2024,7 @@ public class MethodHandles { * that {@linkplain Class#getClassLoader() defined it}. * This means that a class created by a class loader may be unloaded if and * only if its defining loader is not reachable and thus may be reclaimed - * by a garbage collector (JLS 12.7). + * by a garbage collector (JLS {@jls 12.7}). * * By default, however, a hidden class or interface may be unloaded even if * the class loader that is marked as its defining loader is @@ -2759,7 +2759,7 @@ assertEquals("[x, y, z]", pb.command().toString()); /** * Looks up a class by name from the lookup context defined by this {@code Lookup} object, * as if resolved by an {@code ldc} instruction. - * Such a resolution, as specified in JVMS 5.4.3.1 section, attempts to locate and load the class, + * Such a resolution, as specified in JVMS {@jvms 5.4.3.1}, attempts to locate and load the class, * and then determines whether the class is accessible to this lookup object. *

      * The lookup context here is determined by the {@linkplain #lookupClass() lookup class}, @@ -4757,15 +4757,15 @@ return invoker; * the boolean is converted to a byte value, 1 for true, 0 for false. * (This treatment follows the usage of the bytecode verifier.) *

    • If T1 is boolean and T0 is another primitive, - * T0 is converted to byte via Java casting conversion (JLS 5.5), + * T0 is converted to byte via Java casting conversion (JLS {@jls 5.5}), * and the low order bit of the result is tested, as if by {@code (x & 1) != 0}. *
    • If T0 and T1 are primitives other than boolean, - * then a Java casting conversion (JLS 5.5) is applied. + * then a Java casting conversion (JLS {@jls 5.5}) is applied. * (Specifically, T0 will convert to T1 by * widening and/or narrowing.) *
    • If T0 is a reference and T1 a primitive, an unboxing * conversion will be applied at runtime, possibly followed - * by a Java casting conversion (JLS 5.5) on the primitive value, + * by a Java casting conversion (JLS {@jls 5.5}) on the primitive value, * possibly followed by a conversion from byte to boolean by testing * the low-order bit. *
    • If T0 is a reference and T1 a primitive, diff --git a/src/java.base/share/classes/java/lang/invoke/MutableCallSite.java b/src/java.base/share/classes/java/lang/invoke/MutableCallSite.java index c16483d02ae5e87ad6e2ed5ebecddd889bd10145..50ba77d8f96f97add99f969df17bea3937f6deb5 100644 --- a/src/java.base/share/classes/java/lang/invoke/MutableCallSite.java +++ b/src/java.base/share/classes/java/lang/invoke/MutableCallSite.java @@ -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 @@ -83,7 +83,7 @@ assertEquals("Wilma, dear?", (String) worker2.invokeExact()); * @author John Rose, JSR 292 EG * @since 1.7 */ -public class MutableCallSite extends CallSite { +public non-sealed class MutableCallSite extends CallSite { /** * Creates a blank call site object with the given method type. * The initial target is set to a method handle of the given type diff --git a/src/java.base/share/classes/java/lang/invoke/StringConcatFactory.java b/src/java.base/share/classes/java/lang/invoke/StringConcatFactory.java index 5ff0cf84aecc6aae1c6e0af163b6874f7d976c11..7026591190ebc3a27409c47980943dee5f75f6c9 100644 --- a/src/java.base/share/classes/java/lang/invoke/StringConcatFactory.java +++ b/src/java.base/share/classes/java/lang/invoke/StringConcatFactory.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2020, 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 @@ -142,10 +142,10 @@ public final class StringConcatFactory { *
        *
      • zero inputs, concatenation results in an empty string;
      • *
      • one input, concatenation results in the single - * input converted as per JLS 5.1.11 "String Conversion"; otherwise
      • + * input converted as per JLS {@jls 5.1.11} "String Conversion"; otherwise *
      • two or more inputs, the inputs are concatenated as per - * requirements stated in JLS 15.18.1 "String Concatenation Operator +". - * The inputs are converted as per JLS 5.1.11 "String Conversion", + * requirements stated in JLS {@jls 15.18.1} "String Concatenation Operator +". + * The inputs are converted as per JLS {@jls 5.1.11} "String Conversion", * and combined from left to right.
      • *
      * @@ -223,10 +223,10 @@ public final class StringConcatFactory { *
        *
      • zero inputs, concatenation results in an empty string;
      • *
      • one input, concatenation results in the single - * input converted as per JLS 5.1.11 "String Conversion"; otherwise
      • + * input converted as per JLS {@jls 5.1.11} "String Conversion"; otherwise *
      • two or more inputs, the inputs are concatenated as per - * requirements stated in JLS 15.18.1 "String Concatenation Operator +". - * The inputs are converted as per JLS 5.1.11 "String Conversion", + * requirements stated in JLS {@jls 15.18.1} "String Concatenation Operator +". + * The inputs are converted as per JLS {@jls 5.1.11} "String Conversion", * and combined from left to right.
      • *
      * diff --git a/src/java.base/share/classes/java/lang/invoke/VolatileCallSite.java b/src/java.base/share/classes/java/lang/invoke/VolatileCallSite.java index 742fa23737d02e73c851f5807b8e12341e052226..faf10fd79f4934a88e8b25e3fbfd5d2ab0b16283 100644 --- a/src/java.base/share/classes/java/lang/invoke/VolatileCallSite.java +++ b/src/java.base/share/classes/java/lang/invoke/VolatileCallSite.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2011, 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 @@ -42,7 +42,7 @@ package java.lang.invoke; * @author John Rose, JSR 292 EG * @since 1.7 */ -public class VolatileCallSite extends CallSite { +public non-sealed class VolatileCallSite extends CallSite { /** * Creates a call site with a volatile binding to its target. * The initial target is set to a method handle diff --git a/src/java.base/share/classes/java/lang/ref/FinalReference.java b/src/java.base/share/classes/java/lang/ref/FinalReference.java index 9175516d4d0cec03562b36299f4941f4a8d9f583..06af37df67c94e062022a727f4841dd9c9579ef4 100644 --- a/src/java.base/share/classes/java/lang/ref/FinalReference.java +++ b/src/java.base/share/classes/java/lang/ref/FinalReference.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -28,7 +28,7 @@ package java.lang.ref; /** * Final references, used to implement finalization */ -class FinalReference extends Reference { +sealed class FinalReference extends Reference permits Finalizer { public FinalReference(T referent, ReferenceQueue q) { super(referent, q); diff --git a/src/java.base/share/classes/java/lang/ref/PhantomReference.java b/src/java.base/share/classes/java/lang/ref/PhantomReference.java index 2c1532b8eb2956898e8d8ec0515dfce78228e5bc..fef3bc7c50859fe90b8eab967c24a1cef2cf4f52 100644 --- a/src/java.base/share/classes/java/lang/ref/PhantomReference.java +++ b/src/java.base/share/classes/java/lang/ref/PhantomReference.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2022, Oracle and/or its affiliates. All rights reserved. * 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 @@ import jdk.internal.vm.annotation.IntrinsicCandidate; * @since 1.2 */ -public class PhantomReference extends Reference { +public non-sealed class PhantomReference extends Reference { /** * Returns this reference object's referent. Because the referent of a diff --git a/src/java.base/share/classes/java/lang/ref/Reference.java b/src/java.base/share/classes/java/lang/ref/Reference.java index 17d8c7b669c07e7831fd8ae6021aa77bf3f0ee58..777567085ebfa7a2b8e6797b38333e05002ef5d0 100644 --- a/src/java.base/share/classes/java/lang/ref/Reference.java +++ b/src/java.base/share/classes/java/lang/ref/Reference.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2022, Oracle and/or its affiliates. All rights reserved. * 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,8 @@ import jdk.internal.ref.Cleaner; * @since 1.2 */ -public abstract class Reference { +public abstract sealed class Reference + permits PhantomReference, SoftReference, WeakReference, FinalReference { /* The state of a Reference object is characterized by two attributes. It * may be either "active", "pending", or "inactive". It may also be diff --git a/src/java.base/share/classes/java/lang/ref/SoftReference.java b/src/java.base/share/classes/java/lang/ref/SoftReference.java index 8ce74a67d0ad8c3366fe2d8f2244d0f4ab339b53..a0cb75dcf5031060dca3ca837d746ac4d3c12cbe 100644 --- a/src/java.base/share/classes/java/lang/ref/SoftReference.java +++ b/src/java.base/share/classes/java/lang/ref/SoftReference.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2003, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2022, Oracle and/or its affiliates. All rights reserved. * 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,7 +61,7 @@ package java.lang.ref; * @since 1.2 */ -public class SoftReference extends Reference { +public non-sealed class SoftReference extends Reference { /** * Timestamp clock, updated by the garbage collector diff --git a/src/java.base/share/classes/java/lang/ref/WeakReference.java b/src/java.base/share/classes/java/lang/ref/WeakReference.java index fdf2b5c9f023ea1deb48626a376cbdb0135087e6..1d1a01f3acd9624e4a234c64d1f0900ebe3ebfb4 100644 --- a/src/java.base/share/classes/java/lang/ref/WeakReference.java +++ b/src/java.base/share/classes/java/lang/ref/WeakReference.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2003, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2022, Oracle and/or its affiliates. All rights reserved. * 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 @@ package java.lang.ref; * @since 1.2 */ -public class WeakReference extends Reference { +public non-sealed class WeakReference extends Reference { /** * Creates a new weak reference that refers to the given object. The new diff --git a/src/java.base/share/classes/java/lang/reflect/TypeVariable.java b/src/java.base/share/classes/java/lang/reflect/TypeVariable.java index 0064aed2a2203e12ead789f7e33284aea4f74cae..01746e34385088385277365c85b2005f3aaa9368 100644 --- a/src/java.base/share/classes/java/lang/reflect/TypeVariable.java +++ b/src/java.base/share/classes/java/lang/reflect/TypeVariable.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 @@ -30,8 +30,8 @@ package java.lang.reflect; * A type variable is created the first time it is needed by a reflective * method, as specified in this package. If a type variable t is referenced * by a type (i.e, class, interface or annotation type) T, and T is declared - * by the nth enclosing class of T (see JLS 8.1.2), then the creation of t - * requires the resolution (see JVMS 5) of the ith enclosing class of T, + * by the nth enclosing class of T (see JLS {@jls 8.1.2}), then the creation of t + * requires the resolution (see JVMS {@jvms 5}) of the ith enclosing class of T, * for i = 0 to n, inclusive. Creating a type variable must not cause the * creation of its bounds. Repeated creation of a type variable has no effect. * diff --git a/src/java.base/share/classes/java/math/MathContext.java b/src/java.base/share/classes/java/math/MathContext.java index e53db0f05bd9b44e1bea08b58810032e0519a032..da6de74bb58d557993640685097253b131e1b6b7 100644 --- a/src/java.base/share/classes/java/math/MathContext.java +++ b/src/java.base/share/classes/java/math/MathContext.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 @@ -58,7 +58,6 @@ public final class MathContext implements Serializable { /* ----- Constants ----- */ // defaults for constructors - private static final int DEFAULT_DIGITS = 9; private static final RoundingMode DEFAULT_ROUNDINGMODE = RoundingMode.HALF_UP; // Smallest values for digits (Maximum is Integer.MAX_VALUE) private static final int MIN_DIGITS = 0; @@ -140,7 +139,6 @@ public final class MathContext implements Serializable { */ public MathContext(int setPrecision) { this(setPrecision, DEFAULT_ROUNDINGMODE); - return; } /** @@ -162,7 +160,6 @@ public final class MathContext implements Serializable { precision = setPrecision; roundingMode = setRoundingMode; - return; } /** @@ -181,7 +178,6 @@ public final class MathContext implements Serializable { * @throws NullPointerException if the argument is {@code null} */ public MathContext(String val) { - boolean bad = false; int setPrecision; if (val == null) throw new NullPointerException("null String"); @@ -232,7 +228,6 @@ public final class MathContext implements Serializable { * @return a {@code RoundingMode} object which is the value of the * {@code roundingMode} setting */ - public RoundingMode getRoundingMode() { return roundingMode; } diff --git a/src/java.base/share/classes/java/net/DatagramSocket.java b/src/java.base/share/classes/java/net/DatagramSocket.java index 114794be1f9904261ebb8e659424e5824b052e15..1833dd2470dd587ffd139ab0256840caa24c51af 100644 --- a/src/java.base/share/classes/java/net/DatagramSocket.java +++ b/src/java.base/share/classes/java/net/DatagramSocket.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1995, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1995, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -1353,9 +1353,7 @@ public class DatagramSocket implements java.io.Closeable { Throwable cause = e.getCause(); if (cause instanceof SocketException) return (SocketException) cause; - SocketException se = new SocketException(e.getMessage()); - se.initCause(e); - return se; + return new SocketException(e.getMessage(), e); } /** diff --git a/src/java.base/share/classes/java/net/Inet6Address.java b/src/java.base/share/classes/java/net/Inet6Address.java index 751623536e765794de62ce1597af76455d1d5348..325765ff3b621d2dc74bc7b5f7c5682c456ebd6a 100644 --- a/src/java.base/share/classes/java/net/Inet6Address.java +++ b/src/java.base/share/classes/java/net/Inet6Address.java @@ -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 @@ -593,10 +593,6 @@ class Inet6Address extends InetAddress { throws IOException, ClassNotFoundException { NetworkInterface scope_ifname = null; - if (getClass().getClassLoader() != null) { - throw new SecurityException ("invalid address type"); - } - ObjectInputStream.GetField gf = s.readFields(); byte[] ipaddress = (byte[])gf.get("ipaddress", new byte[0]); int scope_id = gf.get("scope_id", -1); diff --git a/src/java.base/share/classes/java/net/InetAddress.java b/src/java.base/share/classes/java/net/InetAddress.java index 3875216768be9deab04ee261dc940cba55f0c336..3bad2755978835aa9a828794510a3f6ee927abb5 100644 --- a/src/java.base/share/classes/java/net/InetAddress.java +++ b/src/java.base/share/classes/java/net/InetAddress.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1995, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1995, 2022, Oracle and/or its affiliates. All rights reserved. * 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,6 +44,7 @@ import java.io.ObjectInputStream; import java.io.ObjectInputStream.GetField; import java.io.ObjectOutputStream; import java.io.ObjectOutputStream.PutField; +import java.io.Serializable; import java.lang.annotation.Native; import java.util.ServiceLoader; import java.util.concurrent.ConcurrentHashMap; @@ -223,7 +224,7 @@ import static java.net.spi.InetAddressResolver.LookupPolicy.IPV6_FIRST; * @see java.net.InetAddress#getLocalHost() * @since 1.0 */ -public class InetAddress implements java.io.Serializable { +public sealed class InetAddress implements Serializable permits Inet4Address, Inet6Address { /** * Specify the address family: Internet Protocol, Version 4 @@ -1769,16 +1770,6 @@ public class InetAddress implements java.io.Serializable { return impl.anyLocalAddress(); } - /** - * Initializes an empty InetAddress. - */ - @java.io.Serial - private void readObjectNoData () { - if (getClass().getClassLoader() != null) { - throw new SecurityException ("invalid address type"); - } - } - private static final jdk.internal.misc.Unsafe UNSAFE = jdk.internal.misc.Unsafe.getUnsafe(); private static final long FIELDS_OFFSET @@ -1794,9 +1785,6 @@ public class InetAddress implements java.io.Serializable { @java.io.Serial private void readObject (ObjectInputStream s) throws IOException, ClassNotFoundException { - if (getClass().getClassLoader() != null) { - throw new SecurityException ("invalid address type"); - } GetField gf = s.readFields(); String host = (String)gf.get("hostName", null); int address = gf.get("address", 0); @@ -1830,11 +1818,7 @@ public class InetAddress implements java.io.Serializable { * @throws IOException if an I/O error occurs */ @java.io.Serial - private void writeObject (ObjectOutputStream s) throws - IOException { - if (getClass().getClassLoader() != null) { - throw new SecurityException ("invalid address type"); - } + private void writeObject (ObjectOutputStream s) throws IOException { PutField pf = s.putFields(); pf.put("hostName", holder().getHostName()); pf.put("address", holder().getAddress()); diff --git a/src/java.base/share/classes/java/net/SocketException.java b/src/java.base/share/classes/java/net/SocketException.java index f4a412258dfa33e7a94dba690a6d1ce044bae77c..7b73824992398380c6c9c55bbeb135fd49ea7fec 100644 --- a/src/java.base/share/classes/java/net/SocketException.java +++ b/src/java.base/share/classes/java/net/SocketException.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1995, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1995, 2022, Oracle and/or its affiliates. All rights reserved. * 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,4 +52,27 @@ public class SocketException extends IOException { */ public SocketException() { } + + /** + * Constructs a new {@code SocketException} with the + * specified detail message and cause. + * + * @param msg the detail message. + * @param cause the cause + * @since 19 + */ + public SocketException(String msg, Throwable cause) { + super(msg, cause); + } + + /** + * Constructs a new {@code SocketException} with the + * specified cause. + * + * @param cause the cause + * @since 19 + */ + public SocketException(Throwable cause) { + super(cause); + } } diff --git a/src/java.base/share/classes/java/nio/Heap-X-Buffer.java.template b/src/java.base/share/classes/java/nio/Heap-X-Buffer.java.template index 53d099396e13b497150b296f2213f11293538fb5..38e18ac625b9121e9f9e04c41ff9f021e8f71d15 100644 --- a/src/java.base/share/classes/java/nio/Heap-X-Buffer.java.template +++ b/src/java.base/share/classes/java/nio/Heap-X-Buffer.java.template @@ -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 @@ -40,10 +40,10 @@ import jdk.internal.access.foreign.MemorySegmentProxy; * instance of this class rather than of the superclass. #end[rw] */ - class Heap$Type$Buffer$RW$ extends {#if[ro]?Heap}$Type$Buffer { +#if[rw] // Cached array base offset private static final long ARRAY_BASE_OFFSET = UNSAFE.arrayBaseOffset($type$[].class); @@ -53,11 +53,10 @@ class Heap$Type$Buffer$RW$ // For speed these fields are actually declared in X-Buffer; // these declarations are here as documentation /* -#if[rw] protected final $type$[] hb; protected final int offset; -#end[rw] */ +#end[rw] Heap$Type$Buffer$RW$(int cap, int lim, MemorySegmentProxy segment) { // package-private #if[rw] diff --git a/src/java.base/share/classes/java/nio/channels/AsynchronousFileChannel.java b/src/java.base/share/classes/java/nio/channels/AsynchronousFileChannel.java index 09054e30f8630e61c11b45f2d6460957d257afd3..2ad51f80a452b2c2f8a1200973fe982f0fb01723 100644 --- a/src/java.base/share/classes/java/nio/channels/AsynchronousFileChannel.java +++ b/src/java.base/share/classes/java/nio/channels/AsynchronousFileChannel.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -425,10 +425,13 @@ public abstract class AsynchronousFileChannel * required then a region starting at zero, and no smaller than the * expected maximum size of the file, should be locked. The two-argument * {@link #lock(Object,CompletionHandler)} method simply locks a region - * of size {@link Long#MAX_VALUE}. If a lock that overlaps the requested - * region is already held by this Java virtual machine, or this method has - * been invoked to lock an overlapping region and that operation has not - * completed, then this method throws {@link OverlappingFileLockException}. + * of size {@link Long#MAX_VALUE}. If the {@code position} is non-negative + * and the {@code size} is zero, then a lock of size + * {@code Long.MAX_VALUE - position} is returned. If a lock that + * overlaps the requested region is already held by this Java virtual + * machine, or this method has been invoked to lock an overlapping region + * and that operation has not completed, then this method throws + * {@link OverlappingFileLockException}. * *

      Some operating systems do not support a mechanism to acquire a file * lock in an asynchronous manner. Consequently an implementation may @@ -454,7 +457,10 @@ public abstract class AsynchronousFileChannel * non-negative * @param size * The size of the locked region; must be non-negative, and the sum - * {@code position} + {@code size} must be non-negative + * {@code position} + {@code size} must be non-negative. + * A value of zero means to lock all bytes from the specified + * starting position to the end of the file, regardless of whether + * the file is subsequently extended or truncated * @param shared * {@code true} to request a shared lock, in which case this * channel must be open for reading (and possibly writing); @@ -532,7 +538,10 @@ public abstract class AsynchronousFileChannel * non-negative * @param size * The size of the locked region; must be non-negative, and the sum - * {@code position} + {@code size} must be non-negative + * {@code position} + {@code size} must be non-negative. + * A value of zero means to lock all bytes from the specified + * starting position to the end of the file, regardless of whether + * the file is subsequently extended or truncated * @param shared * {@code true} to request a shared lock, in which case this * channel must be open for reading (and possibly writing); @@ -586,7 +595,9 @@ public abstract class AsynchronousFileChannel * either having acquired a lock on the requested region or having failed to * do so. If it fails to acquire a lock because an overlapping lock is held * by another program then it returns {@code null}. If it fails to acquire - * a lock for any other reason then an appropriate exception is thrown. + * a lock for any other reason then an appropriate exception is thrown. If + * the {@code position} is non-negative and the {@code size} is zero, then a + * lock of size {@code Long.MAX_VALUE - position} is returned. * * @param position * The position at which the locked region is to start; must be @@ -594,7 +605,10 @@ public abstract class AsynchronousFileChannel * * @param size * The size of the locked region; must be non-negative, and the sum - * {@code position} + {@code size} must be non-negative + * {@code position} + {@code size} must be non-negative. + * A value of zero means to lock all bytes from the specified + * starting position to the end of the file, regardless of whether + * the file is subsequently extended or truncated * * @param shared * {@code true} to request a shared lock, diff --git a/src/java.base/share/classes/java/nio/channels/FileChannel.java b/src/java.base/share/classes/java/nio/channels/FileChannel.java index 9d9c35fbc1f760c8b829b869ddc7b897c5212671..524e8e67cee08fcd3792207a43607e136cf39ffb 100644 --- a/src/java.base/share/classes/java/nio/channels/FileChannel.java +++ b/src/java.base/share/classes/java/nio/channels/FileChannel.java @@ -996,7 +996,9 @@ public abstract class FileChannel * required then a region starting at zero, and no smaller than the * expected maximum size of the file, should be locked. The zero-argument * {@link #lock()} method simply locks a region of size {@link - * Long#MAX_VALUE}. + * Long#MAX_VALUE}. If the {@code position} is non-negative and the + * {@code size} is zero, then a lock of size + * {@code Long.MAX_VALUE - position} is returned. * *

      Some operating systems do not support shared locks, in which case a * request for a shared lock is automatically converted into a request for @@ -1014,7 +1016,10 @@ public abstract class FileChannel * * @param size * The size of the locked region; must be non-negative, and the sum - * {@code position} + {@code size} must be non-negative + * {@code position} + {@code size} must be non-negative. + * A value of zero means to lock all bytes from the specified + * starting position to the end of the file, regardless of whether + * the file is subsequently extended or truncated * * @param shared * {@code true} to request a shared lock, in which case this @@ -1123,7 +1128,9 @@ public abstract class FileChannel * required then a region starting at zero, and no smaller than the * expected maximum size of the file, should be locked. The zero-argument * {@link #tryLock()} method simply locks a region of size {@link - * Long#MAX_VALUE}. + * Long#MAX_VALUE}. If the {@code position} is non-negative and the + * {@code size} is zero, then a lock of size + * {@code Long.MAX_VALUE - position} is returned. * *

      Some operating systems do not support shared locks, in which case a * request for a shared lock is automatically converted into a request for @@ -1141,7 +1148,10 @@ public abstract class FileChannel * * @param size * The size of the locked region; must be non-negative, and the sum - * {@code position} + {@code size} must be non-negative + * {@code position} + {@code size} must be non-negative. + * A value of zero means to lock all bytes from the specified + * starting position to the end of the file, regardless of whether + * the file is subsequently extended or truncated * * @param shared * {@code true} to request a shared lock, diff --git a/src/java.base/share/classes/java/nio/channels/FileLock.java b/src/java.base/share/classes/java/nio/channels/FileLock.java index 0edd94d5e2520d0e31c64d35ffcd193627ad101f..3bd0b9c7b2ca988b27fe8a81723f553568c6f7ea 100644 --- a/src/java.base/share/classes/java/nio/channels/FileLock.java +++ b/src/java.base/share/classes/java/nio/channels/FileLock.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2013, 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 @@ -269,14 +269,36 @@ public abstract class FileLock implements AutoCloseable { * @param size * The size of the lock range * - * @return {@code true} if, and only if, this lock and the given lock - * range overlap by at least one byte + * @return {@code true} if this lock and the given lock range overlap + * by at least one byte; {@code false} if {@code size} is + * negative or the lock range does not overlap this lock */ public final boolean overlaps(long position, long size) { - if (position + size <= this.position) - return false; // That is below this - if (this.position + this.size <= position) - return false; // This is below that + if (size < 0) + return false; + + // Test whether this is below that + try { + if (Math.addExact(this.position, this.size) <= position) + return false; + } catch (ArithmeticException ignored) { + // the sum of this.position and this.size overflows the range of + // long hence their mathematical sum is greater than position + } + + // if size == 0 then the specified lock range is unbounded and + // cannot be below the range of this lock + if (size > 0) { + // Test whether that is below this + try { + if (Math.addExact(position, size) <= this.position) + return false; + } catch (ArithmeticException ignored) { + // the sum of position and size overflows the range of long + // hence their mathematical sum is greater than this.position + } + } + return true; } diff --git a/src/java.base/share/classes/java/nio/file/CopyMoveHelper.java b/src/java.base/share/classes/java/nio/file/CopyMoveHelper.java index ab9281807fdcd314b8072133d1268be3be3f784c..e5ca66fa631acbfbea06d6172868eb4bf3d8734f 100644 --- a/src/java.base/share/classes/java/nio/file/CopyMoveHelper.java +++ b/src/java.base/share/classes/java/nio/file/CopyMoveHelper.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 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 @@ -105,11 +105,20 @@ class CopyMoveHelper { LinkOption[] linkOptions = (opts.followLinks) ? new LinkOption[0] : new LinkOption[] { LinkOption.NOFOLLOW_LINKS }; + // retrieve source posix view, null if unsupported + final PosixFileAttributeView sourcePosixView = + Files.getFileAttributeView(source, PosixFileAttributeView.class); + // attributes of source file - BasicFileAttributes attrs = Files.readAttributes(source, - BasicFileAttributes.class, - linkOptions); - if (attrs.isSymbolicLink()) + BasicFileAttributes sourceAttrs = sourcePosixView != null ? + Files.readAttributes(source, + PosixFileAttributes.class, + linkOptions) : + Files.readAttributes(source, + BasicFileAttributes.class, + linkOptions); + + if (sourceAttrs.isSymbolicLink()) throw new IOException("Copying of symbolic links not supported"); // delete target if it exists and REPLACE_EXISTING is specified @@ -119,7 +128,7 @@ class CopyMoveHelper { throw new FileAlreadyExistsException(target.toString()); // create directory or copy file - if (attrs.isDirectory()) { + if (sourceAttrs.isDirectory()) { Files.createDirectory(target); } else { try (InputStream in = Files.newInputStream(source)) { @@ -127,14 +136,29 @@ class CopyMoveHelper { } } - // copy basic attributes to target + // copy basic and, if supported, POSIX attributes to target if (opts.copyAttributes) { - BasicFileAttributeView view = - Files.getFileAttributeView(target, BasicFileAttributeView.class); + BasicFileAttributeView targetView = null; + if (sourcePosixView != null) { + targetView = Files.getFileAttributeView(target, + PosixFileAttributeView.class); + } + + // target might not support posix even if source does + if (targetView == null) { + targetView = Files.getFileAttributeView(target, + BasicFileAttributeView.class); + } + try { - view.setTimes(attrs.lastModifiedTime(), - attrs.lastAccessTime(), - attrs.creationTime()); + targetView.setTimes(sourceAttrs.lastModifiedTime(), + sourceAttrs.lastAccessTime(), + sourceAttrs.creationTime()); + + if (sourceAttrs instanceof PosixFileAttributes sourcePosixAttrs && + targetView instanceof PosixFileAttributeView targetPosixView) { + targetPosixView.setPermissions(sourcePosixAttrs.permissions()); + } } catch (Throwable x) { // rollback try { diff --git a/src/java.base/share/classes/java/security/cert/X509Certificate.java b/src/java.base/share/classes/java/security/cert/X509Certificate.java index bc0df9b45a17147fc8962d85b6ba8fc4e21e10e3..127f60b41806cdb1a908328fd4aef35be42d815b 100644 --- a/src/java.base/share/classes/java/security/cert/X509Certificate.java +++ b/src/java.base/share/classes/java/security/cert/X509Certificate.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -562,6 +562,10 @@ implements X509Extension { * uniformResourceIdentifier [6] IA5String, * iPAddress [7] OCTET STRING, * registeredID [8] OBJECT IDENTIFIER} + * + * OtherName ::= SEQUENCE { + * type-id OBJECT IDENTIFIER, + * value [0] EXPLICIT ANY DEFINED BY type-id } * *

      * If this certificate does not contain a {@code SubjectAltName} @@ -571,7 +575,7 @@ implements X509Extension { * {@code List} whose first entry is an {@code Integer} * (the name type, 0-8) and whose second entry is a {@code String} * or a byte array (the name, in string or ASN.1 DER encoded form, - * respectively). + * respectively). More entries may exist depending on the name type. *

      * RFC 822, DNS, and URI * names are returned as {@code String}s, @@ -581,12 +585,18 @@ implements X509Extension { * in the form "a1:a2:...:a8", where a1-a8 are hexadecimal values * representing the eight 16-bit pieces of the address. OID names are * returned as {@code String}s represented as a series of nonnegative - * integers separated by periods. And directory names (distinguished names) + * integers separated by periods. Directory names (distinguished names) * are returned in - * RFC 2253 string format. No standard string format is - * defined for otherNames, X.400 names, EDI party names, or any - * other type of names. They are returned as byte arrays - * containing the ASN.1 DER encoded form of the name. + * RFC 2253 string format. No standard string format is defined for + * X.400 names or EDI party names. They are returned as byte arrays + * containing the ASN.1 DER encoded form of the name. otherNames are also + * returned as byte arrays containing the ASN.1 DER encoded form of the + * name. A third entry may also be present in the list containing the + * {@code type-id} of the otherName in string form, and a fourth entry + * containing its {@code value} as either a string (if the value is + * a valid supported character string) or a byte array containing the + * ASN.1 DER encoded form of the value without the context-specific + * constructed tag with number 0. *

      * Note that the {@code Collection} returned may contain more * than one name of the same type. Also, note that the returned @@ -599,6 +609,9 @@ implements X509Extension { * and it provides a default implementation. Subclasses * should override this method with a correct implementation. * + * @implNote The JDK SUN provider supports the third and fourth + * otherName entries. + * * @return an immutable {@code Collection} of subject alternative * names (or {@code null}) * @throws CertificateParsingException if the extension cannot be decoded @@ -627,7 +640,8 @@ implements X509Extension { * {@code List} whose first entry is an {@code Integer} * (the name type, 0-8) and whose second entry is a {@code String} * or a byte array (the name, in string or ASN.1 DER encoded form, - * respectively). For more details about the formats used for each + * respectively). More entries may exist depending on the name type. + * For more details about the formats used for each * name type, see the {@code getSubjectAlternativeNames} method. *

      * Note that the {@code Collection} returned may contain more diff --git a/src/java.base/share/classes/java/text/DecimalFormat.java b/src/java.base/share/classes/java/text/DecimalFormat.java index ea125b7d14bbb938756055fda5e351adda03f5b5..094a5258b09d605211b6a479d86afc821e1a95d6 100644 --- a/src/java.base/share/classes/java/text/DecimalFormat.java +++ b/src/java.base/share/classes/java/text/DecimalFormat.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -3210,16 +3210,18 @@ public class DecimalFormat extends NumberFormat { for (i = digitCount; i > 0; --i) { if (i != digitCount && isGroupingUsed() && groupingSize != 0 && i % groupingSize == 0) { - result.append(localized ? symbols.getGroupingSeparator() : - PATTERN_GROUPING_SEPARATOR); + result.append(localized ? + (isCurrencyFormat ? symbols.getMonetaryGroupingSeparator() : symbols.getGroupingSeparator()) : + PATTERN_GROUPING_SEPARATOR); } result.append(i <= getMinimumIntegerDigits() ? (localized ? symbols.getZeroDigit() : PATTERN_ZERO_DIGIT) : (localized ? symbols.getDigit() : PATTERN_DIGIT)); } if (getMaximumFractionDigits() > 0 || decimalSeparatorAlwaysShown) - result.append(localized ? symbols.getDecimalSeparator() : - PATTERN_DECIMAL_SEPARATOR); + result.append(localized ? + (isCurrencyFormat ? symbols.getMonetaryDecimalSeparator() : symbols.getDecimalSeparator()) : + PATTERN_DECIMAL_SEPARATOR); for (i = 0; i < getMaximumFractionDigits(); ++i) { if (i < getMinimumFractionDigits()) { result.append(localized ? symbols.getZeroDigit() : diff --git a/src/java.base/share/classes/java/text/DecimalFormatSymbols.java b/src/java.base/share/classes/java/text/DecimalFormatSymbols.java index 11fd24573ef877e58178fa9a2e506b9e733be377..795e087a35174514f2d6ccc33aed10c705479e83 100644 --- a/src/java.base/share/classes/java/text/DecimalFormatSymbols.java +++ b/src/java.base/share/classes/java/text/DecimalFormatSymbols.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -188,6 +188,15 @@ public class DecimalFormatSymbols implements Cloneable, Serializable { return dfsyms; } + /** + * {@return locale used to create this instance} + * + * @since 19 + */ + public Locale getLocale() { + return locale; + } + /** * Gets the character used for zero. Different for Arabic, etc. * diff --git a/src/java.base/share/classes/java/time/ZoneId.java b/src/java.base/share/classes/java/time/ZoneId.java index fc9dcc4e0543f8a8c0fbc6496e3d6be58834ea82..829ed5f2fdf25724caebfcaacdc8bcc8894a3974 100644 --- a/src/java.base/share/classes/java/time/ZoneId.java +++ b/src/java.base/share/classes/java/time/ZoneId.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 @@ -169,14 +169,14 @@ import static java.util.Map.entry; * The {@code equals} method should be used for comparisons. * * @implSpec - * This abstract class has two implementations, both of which are immutable and thread-safe. - * One implementation models region-based IDs, the other is {@code ZoneOffset} modelling - * offset-based IDs. This difference is visible in serialization. + * This abstract sealed class permits two implementations, both of which are immutable and + * thread-safe. One implementation models region-based IDs, the other is {@code ZoneOffset} + * modelling offset-based IDs. This difference is visible in serialization. * * @since 1.8 */ @jdk.internal.ValueBased -public abstract class ZoneId implements Serializable { +public abstract sealed class ZoneId implements Serializable permits ZoneOffset, ZoneRegion { /** * A map of zone overrides to enable the short time-zone names to be used. @@ -471,11 +471,7 @@ public abstract class ZoneId implements Serializable { /** * Constructor only accessible within the package. */ - ZoneId() { - if (getClass() != ZoneOffset.class && getClass() != ZoneRegion.class) { - throw new AssertionError("Invalid subclass"); - } - } + ZoneId() {} //----------------------------------------------------------------------- /** diff --git a/src/java.base/share/classes/java/time/format/DateTimeFormatter.java b/src/java.base/share/classes/java/time/format/DateTimeFormatter.java index 0a67e22c0f37ff370518847c07fc3dc32de3a61e..d5a5c162fd2de72fd15ed357a03b67e6888fffe2 100644 --- a/src/java.base/share/classes/java/time/format/DateTimeFormatter.java +++ b/src/java.base/share/classes/java/time/format/DateTimeFormatter.java @@ -297,7 +297,7 @@ import sun.util.locale.provider.TimeZoneNameUtility; * W week-of-month number 4 * E day-of-week text Tue; Tuesday; T * e/c localized day-of-week number/text 2; 02; Tue; Tuesday; T - * F day-of-week-in-month number 3 + * F aligned-week-of-month number 3 * * a am-pm-of-day text PM * B period-of-day text in the morning @@ -1573,7 +1573,7 @@ public final class DateTimeFormatter { /** * Gets the DecimalStyle to be used during formatting. * - * @return the locale of this formatter, not null + * @return the DecimalStyle of this formatter, not null */ public DecimalStyle getDecimalStyle() { return decimalStyle; diff --git a/src/java.base/share/classes/java/time/format/DateTimeFormatterBuilder.java b/src/java.base/share/classes/java/time/format/DateTimeFormatterBuilder.java index 62ea488ede7fc83e765fc5ac93c9b370004343c9..d45bfa03f9181766518936137555b6a8dc420861 100644 --- a/src/java.base/share/classes/java/time/format/DateTimeFormatterBuilder.java +++ b/src/java.base/share/classes/java/time/format/DateTimeFormatterBuilder.java @@ -1774,7 +1774,7 @@ public final class DateTimeFormatterBuilder { * D 1 appendValue(ChronoField.DAY_OF_YEAR) * DD 2 appendValue(ChronoField.DAY_OF_YEAR, 2, 3, SignStyle.NOT_NEGATIVE) * DDD 3 appendValue(ChronoField.DAY_OF_YEAR, 3) - * F 1 appendValue(ChronoField.ALIGNED_DAY_OF_WEEK_IN_MONTH) + * F 1 appendValue(ChronoField.ALIGNED_WEEK_OF_MONTH) * g..g 1..n appendValue(JulianFields.MODIFIED_JULIAN_DAY, n, 19, SignStyle.NORMAL) * E 1 appendText(ChronoField.DAY_OF_WEEK, TextStyle.SHORT) * EE 2 appendText(ChronoField.DAY_OF_WEEK, TextStyle.SHORT) @@ -2183,7 +2183,7 @@ public final class DateTimeFormatterBuilder { FIELD_MAP.put('L', ChronoField.MONTH_OF_YEAR); // SDF, LDML (stand-alone) FIELD_MAP.put('D', ChronoField.DAY_OF_YEAR); // SDF, LDML FIELD_MAP.put('d', ChronoField.DAY_OF_MONTH); // SDF, LDML - FIELD_MAP.put('F', ChronoField.ALIGNED_DAY_OF_WEEK_IN_MONTH); // SDF, LDML + FIELD_MAP.put('F', ChronoField.ALIGNED_WEEK_OF_MONTH); // SDF, LDML FIELD_MAP.put('E', ChronoField.DAY_OF_WEEK); // SDF, LDML (different to both for 1/2 chars) FIELD_MAP.put('c', ChronoField.DAY_OF_WEEK); // LDML (stand-alone) FIELD_MAP.put('e', ChronoField.DAY_OF_WEEK); // LDML (needs localized week number) diff --git a/src/java.base/share/classes/java/util/EnumSet.java b/src/java.base/share/classes/java/util/EnumSet.java index ee475ba338a50a571a4face0b36d49081c6a3808..3776cedd5bb9b1233d7bed8c6fcd90f8c15d3072 100644 --- a/src/java.base/share/classes/java/util/EnumSet.java +++ b/src/java.base/share/classes/java/util/EnumSet.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 @@ -76,8 +76,8 @@ import jdk.internal.access.SharedSecrets; * @since 1.5 * @see EnumMap */ -public abstract class EnumSet> extends AbstractSet - implements Cloneable, java.io.Serializable +public abstract sealed class EnumSet> extends AbstractSet + implements Cloneable, java.io.Serializable permits JumboEnumSet, RegularEnumSet { // declare EnumSet.class serialization compatibility with JDK 8 @java.io.Serial diff --git a/src/java.base/share/classes/java/util/Formatter.java b/src/java.base/share/classes/java/util/Formatter.java index 65f67656087b7aa86652ed7b93ba5f19d2e82eae..5c5859c767dc3a0e729e2e38e23d04e12bd4555e 100644 --- a/src/java.base/share/classes/java/util/Formatter.java +++ b/src/java.base/share/classes/java/util/Formatter.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 @@ -2008,15 +2008,41 @@ import sun.util.locale.provider.ResourceBundleBasedAdapter; * @since 1.5 */ public final class Formatter implements Closeable, Flushable { + // Caching DecimalFormatSymbols. Non-volatile to avoid thread slamming. + private static DecimalFormatSymbols DFS = null; + private static DecimalFormatSymbols getDecimalFormatSymbols(Locale locale) { + // Capture local copy to avoid thread race. + DecimalFormatSymbols dfs = DFS; + if (dfs != null && dfs.getLocale().equals(locale)) { + return dfs; + } + // Fetch a new local instance of DecimalFormatSymbols. Note that DFS are mutable + // and this instance is reserved for Formatter. + dfs = DecimalFormatSymbols.getInstance(locale); + // Non-volatile here is acceptable heuristic. + DFS = dfs; + return dfs; + } + + // Use zero from cached DecimalFormatSymbols. + private static char getZero(Locale locale) { + return locale == null ? '0' : getDecimalFormatSymbols(locale).getZeroDigit(); + } + + // Use decimal separator from cached DecimalFormatSymbols. + private static char getDecimalSeparator(Locale locale) { + return locale == null ? '.' : getDecimalFormatSymbols(locale).getDecimalSeparator(); + } + + // Use grouping separator from cached DecimalFormatSymbols. + private static char getGroupingSeparator(Locale locale) { + return locale == null ? ',' : getDecimalFormatSymbols(locale).getGroupingSeparator(); + } + private Appendable a; private final Locale l; - private IOException lastException; - // Non-character value used to mark zero as uninitialized - private static final char ZERO_SENTINEL = '\uFFFE'; - private char zero = ZERO_SENTINEL; - /** * Returns a charset object for the given charset name. * @throws NullPointerException is csn is null @@ -2523,20 +2549,6 @@ public final class Formatter implements Closeable, Flushable { this(l, new BufferedWriter(new OutputStreamWriter(os, charset))); } - private char zero() { - char zero = this.zero; - if (zero == ZERO_SENTINEL) { - if ((l != null) && !l.equals(Locale.US)) { - DecimalFormatSymbols dfs = DecimalFormatSymbols.getInstance(l); - zero = dfs.getZeroDigit(); - } else { - zero = '0'; - } - this.zero = zero; - } - return zero; - } - /** * Returns the locale set by the construction of this formatter. * @@ -4498,14 +4510,6 @@ public final class Formatter implements Closeable, Flushable { throw new IllegalFormatConversionException(c, arg.getClass()); } - private char getZero(Formatter fmt, Locale l) { - if ((l != null) && !l.equals(fmt.locale())) { - DecimalFormatSymbols dfs = DecimalFormatSymbols.getInstance(l); - return dfs.getZeroDigit(); - } - return fmt.zero(); - } - private StringBuilder localizedMagnitude(Formatter fmt, StringBuilder sb, long value, int flags, int width, Locale l) { return localizedMagnitude(fmt, sb, Long.toString(value, 10), 0, flags, width, l); @@ -4519,7 +4523,7 @@ public final class Formatter implements Closeable, Flushable { } int begin = sb.length(); - char zero = getZero(fmt, l); + char zero = getZero(l); // determine localized grouping separator and size char grpSep = '\0'; @@ -4536,21 +4540,15 @@ public final class Formatter implements Closeable, Flushable { } if (dot < len) { - if (l == null || l.equals(Locale.US)) { - decSep = '.'; - } else { - DecimalFormatSymbols dfs = DecimalFormatSymbols.getInstance(l); - decSep = dfs.getDecimalSeparator(); - } + decSep = getDecimalSeparator(l); } if (Flags.contains(f, Flags.GROUP)) { + grpSep = getGroupingSeparator(l); + if (l == null || l.equals(Locale.US)) { - grpSep = ','; grpSize = 3; } else { - DecimalFormatSymbols dfs = DecimalFormatSymbols.getInstance(l); - grpSep = dfs.getGroupingSeparator(); DecimalFormat df = null; NumberFormat nf = NumberFormat.getNumberInstance(l); if (nf instanceof DecimalFormat) { @@ -4567,7 +4565,7 @@ public final class Formatter implements Closeable, Flushable { } String[] all = adapter.getLocaleResources(l) .getNumberPatterns(); - df = new DecimalFormat(all[0], dfs); + df = new DecimalFormat(all[0], getDecimalFormatSymbols(l)); } grpSize = df.getGroupingSize(); // Some locales do not use grouping (the number @@ -4612,7 +4610,7 @@ public final class Formatter implements Closeable, Flushable { // group separators is added for any locale. private void localizedMagnitudeExp(Formatter fmt, StringBuilder sb, char[] value, final int offset, Locale l) { - char zero = getZero(fmt, l); + char zero = getZero(l); int len = value.length; for (int j = offset; j < len; j++) { diff --git a/src/java.base/share/classes/java/util/HashMap.java b/src/java.base/share/classes/java/util/HashMap.java index 24fcd9516ca475245ffb470f79849faa52eb14f4..997273aa104f1575ebe8d62273da59b6e35b0d16 100644 --- a/src/java.base/share/classes/java/util/HashMap.java +++ b/src/java.base/share/classes/java/util/HashMap.java @@ -495,9 +495,9 @@ public class HashMap extends AbstractMap int s = m.size(); if (s > 0) { if (table == null) { // pre-size - float ft = ((float)s / loadFactor) + 1.0F; - int t = ((ft < (float)MAXIMUM_CAPACITY) ? - (int)ft : MAXIMUM_CAPACITY); + double dt = Math.ceil(s / (double)loadFactor); + int t = ((dt < (double)MAXIMUM_CAPACITY) ? + (int)dt : MAXIMUM_CAPACITY); if (t > threshold) threshold = tableSizeFor(t); } else { @@ -1527,12 +1527,12 @@ public class HashMap extends AbstractMap } else if (mappings == 0) { // use defaults } else if (mappings > 0) { - float fc = (float)mappings / lf + 1.0f; - int cap = ((fc < DEFAULT_INITIAL_CAPACITY) ? + double dc = Math.ceil(mappings / (double)lf); + int cap = ((dc < DEFAULT_INITIAL_CAPACITY) ? DEFAULT_INITIAL_CAPACITY : - (fc >= MAXIMUM_CAPACITY) ? + (dc >= MAXIMUM_CAPACITY) ? MAXIMUM_CAPACITY : - tableSizeFor((int)fc)); + tableSizeFor((int)dc)); float ft = (float)cap * lf; threshold = ((cap < MAXIMUM_CAPACITY && ft < MAXIMUM_CAPACITY) ? (int)ft : Integer.MAX_VALUE); diff --git a/src/java.base/share/classes/java/util/JumboEnumSet.java b/src/java.base/share/classes/java/util/JumboEnumSet.java index f80e5056803b37c75c5201639b247811d0802cbe..126fc077b6cd40c890a208ced45d40c704d14d9c 100644 --- a/src/java.base/share/classes/java/util/JumboEnumSet.java +++ b/src/java.base/share/classes/java/util/JumboEnumSet.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 @@ -33,7 +33,7 @@ package java.util; * @since 1.5 * @serial exclude */ -class JumboEnumSet> extends EnumSet { +final class JumboEnumSet> extends EnumSet { @java.io.Serial private static final long serialVersionUID = 334349849919042784L; diff --git a/src/java.base/share/classes/java/util/Objects.java b/src/java.base/share/classes/java/util/Objects.java index 0b727d6310b6b26af562476956d497150c595312..066c20d6551850efe91adb278298e2b25e46faf8 100644 --- a/src/java.base/share/classes/java/util/Objects.java +++ b/src/java.base/share/classes/java/util/Objects.java @@ -227,6 +227,7 @@ public final class Objects { * @return {@code obj} if not {@code null} * @throws NullPointerException if {@code obj} is {@code null} */ + @ForceInline public static T requireNonNull(T obj) { if (obj == null) throw new NullPointerException(); @@ -252,6 +253,7 @@ public final class Objects { * @return {@code obj} if not {@code null} * @throws NullPointerException if {@code obj} is {@code null} */ + @ForceInline public static T requireNonNull(T obj, String message) { if (obj == null) throw new NullPointerException(message); diff --git a/src/java.base/share/classes/java/util/RegularEnumSet.java b/src/java.base/share/classes/java/util/RegularEnumSet.java index 1deda8a293529c065e08156a1e2542cadc84de50..f06adcbf692c1b4980c255daca7301f3af746f0c 100644 --- a/src/java.base/share/classes/java/util/RegularEnumSet.java +++ b/src/java.base/share/classes/java/util/RegularEnumSet.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 @@ -33,7 +33,7 @@ package java.util; * @since 1.5 * @serial exclude */ -class RegularEnumSet> extends EnumSet { +final class RegularEnumSet> extends EnumSet { @java.io.Serial private static final long serialVersionUID = 3411599620347842686L; /** diff --git a/src/java.base/share/classes/java/util/ResourceBundle.java b/src/java.base/share/classes/java/util/ResourceBundle.java index 052de0555c7bbdb01a6d1f0ac64d74755fc05d53..2e6ecf465826a8f2f14e58f5f35025787a890851 100644 --- a/src/java.base/share/classes/java/util/ResourceBundle.java +++ b/src/java.base/share/classes/java/util/ResourceBundle.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -256,6 +256,12 @@ import static sun.security.util.SecurityConstants.GET_CLASSLOADER_PERMISSION; * resource bundle provider, it does not fall back to the * class loader search. * + *

      + * In cases where the {@code getBundle} factory method is called from a context + * where there is no caller frame on the stack (e.g. when called directly from + * a JNI attached thread), the caller module is default to the unnamed module for the + * {@linkplain ClassLoader#getSystemClassLoader system class loader}. + * *

      Resource bundles in automatic modules

      * * A common format of resource bundles is in {@linkplain PropertyResourceBundle @@ -1505,7 +1511,8 @@ public abstract class ResourceBundle { } private static Control getDefaultControl(Class caller, String baseName) { - return getDefaultControl(caller.getModule(), baseName); + Module callerModule = getCallerModule(caller); + return getDefaultControl(callerModule, baseName); } private static Control getDefaultControl(Module targetModule, String baseName) { @@ -1536,7 +1543,8 @@ public abstract class ResourceBundle { } private static void checkNamedModule(Class caller) { - if (caller.getModule().isNamed()) { + Module callerModule = getCallerModule(caller); + if (callerModule.isNamed()) { throw new UnsupportedOperationException( "ResourceBundle.Control not supported in named modules"); } @@ -1546,7 +1554,19 @@ public abstract class ResourceBundle { Locale locale, Class caller, Control control) { - return getBundleImpl(baseName, locale, caller, caller.getClassLoader(), control); + ClassLoader loader = getLoader(getCallerModule(caller)); + return getBundleImpl(baseName, locale, caller, loader, control); + } + + /* + * Determine the module to be used for the caller. If + * Reflection::getCallerClass is called from JNI with an empty + * stack frame the caller will be null, so the system class loader unnamed + * module will be used. + */ + private static Module getCallerModule(Class caller) { + return (caller != null) ? caller.getModule() + : ClassLoader.getSystemClassLoader().getUnnamedModule(); } /** @@ -1565,10 +1585,7 @@ public abstract class ResourceBundle { Class caller, ClassLoader loader, Control control) { - if (caller == null) { - throw new InternalError("null caller"); - } - Module callerModule = caller.getModule(); + Module callerModule = getCallerModule(caller); // get resource bundles for a named module only if loader is the module's class loader if (callerModule.isNamed() && loader == getLoader(callerModule)) { @@ -1592,7 +1609,7 @@ public abstract class ResourceBundle { Locale locale, Control control) { Objects.requireNonNull(module); - Module callerModule = caller.getModule(); + Module callerModule = getCallerModule(caller); if (callerModule != module) { @SuppressWarnings("removal") SecurityManager sm = System.getSecurityManager(); @@ -2228,9 +2245,9 @@ public abstract class ResourceBundle { */ @CallerSensitive public static final void clearCache() { - Class caller = Reflection.getCallerClass(); + Module callerModule = getCallerModule(Reflection.getCallerClass()); cacheList.keySet().removeIf( - key -> key.getCallerModule() == caller.getModule() + key -> key.getCallerModule() == callerModule ); } diff --git a/src/java.base/share/classes/java/util/WeakHashMap.java b/src/java.base/share/classes/java/util/WeakHashMap.java index 03aee09e992f52447a799f53292c0cf533a909f1..bc31985b66ee2f68928600d32bb2f89acad0cb2e 100644 --- a/src/java.base/share/classes/java/util/WeakHashMap.java +++ b/src/java.base/share/classes/java/util/WeakHashMap.java @@ -213,9 +213,7 @@ public class WeakHashMap if (loadFactor <= 0 || Float.isNaN(loadFactor)) throw new IllegalArgumentException("Illegal Load factor: "+ loadFactor); - int capacity = 1; - while (capacity < initialCapacity) - capacity <<= 1; + int capacity = HashMap.tableSizeFor(initialCapacity); table = newTable(capacity); this.loadFactor = loadFactor; threshold = (int)(capacity * loadFactor); @@ -251,7 +249,7 @@ public class WeakHashMap * @since 1.3 */ public WeakHashMap(Map m) { - this(Math.max((int) ((float)m.size() / DEFAULT_LOAD_FACTOR + 1.0F), + this(Math.max((int) Math.ceil(m.size() / (double)DEFAULT_LOAD_FACTOR), DEFAULT_INITIAL_CAPACITY), DEFAULT_LOAD_FACTOR); putAll(m); @@ -468,7 +466,7 @@ public class WeakHashMap modCount++; Entry e = tab[i]; tab[i] = new Entry<>(k, value, queue, h, e); - if (++size >= threshold) + if (++size > threshold) resize(tab.length * 2); return null; } @@ -557,7 +555,7 @@ public class WeakHashMap * to at most one extra resize. */ if (numKeysToBeAdded > threshold) { - int targetCapacity = (int)(numKeysToBeAdded / loadFactor + 1); + int targetCapacity = (int)Math.ceil(numKeysToBeAdded / (double)loadFactor); if (targetCapacity > MAXIMUM_CAPACITY) targetCapacity = MAXIMUM_CAPACITY; int newCapacity = table.length; @@ -1040,7 +1038,7 @@ public class WeakHashMap Objects.requireNonNull(function); int expectedModCount = modCount; - Entry[] tab = getTable();; + Entry[] tab = getTable(); for (Entry entry : tab) { while (entry != null) { Object key = entry.get(); diff --git a/src/java.base/share/classes/java/util/jar/JarFile.java b/src/java.base/share/classes/java/util/jar/JarFile.java index f0cd0e5c3820fb7ed0bcb57aa08d8455cc8e7e54..e6a55b9cb273b0c9e851d71a5cd81bb4a0a975bd 100644 --- a/src/java.base/share/classes/java/util/jar/JarFile.java +++ b/src/java.base/share/classes/java/util/jar/JarFile.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -826,7 +826,8 @@ public class JarFile extends ZipFile { * zip file entry. * @param ze the zip file entry * @return an input stream for reading the contents of the specified - * zip file entry + * zip file entry or null if the zip file entry does not exist + * within the jar file * @throws ZipException if a zip file format error has occurred * @throws IOException if an I/O error has occurred * @throws SecurityException if any of the jar file entries @@ -837,6 +838,8 @@ public class JarFile extends ZipFile { public synchronized InputStream getInputStream(ZipEntry ze) throws IOException { + Objects.requireNonNull(ze, "ze"); + maybeInstantiateVerifier(); if (jv == null) { return super.getInputStream(ze); @@ -850,21 +853,33 @@ public class JarFile extends ZipFile { if (jv == null) return super.getInputStream(ze); } - + // Return null InputStream when the specified entry is not found in the + // Jar + var je = verifiableEntry(ze); + if (je == null) { + return null; + } // wrap a verifier stream around the real stream return new JarVerifier.VerifierStream( - getManifestFromReference(), - verifiableEntry(ze), - super.getInputStream(ze), - jv); + getManifestFromReference(), + je, + super.getInputStream(ze), + jv); + } - private JarEntry verifiableEntry(ZipEntry ze) { + private JarEntry verifiableEntry(ZipEntry ze) throws ZipException { if (ze instanceof JarFileEntry) { // assure the name and entry match for verification return ((JarFileEntry)ze).realEntry(); } - ze = getJarEntry(ze.getName()); + // ZipEntry::getName should not return null, if it does, return null + var entryName = ze.getName(); + if (entryName != null) { + ze = getJarEntry(entryName); + } else { + return null; + } if (ze instanceof JarFileEntry) { return ((JarFileEntry)ze).realEntry(); } diff --git a/src/java.base/share/classes/java/util/regex/Pattern.java b/src/java.base/share/classes/java/util/regex/Pattern.java index b1e3977d0b2b3125950b88ea94a9e5a201b7374a..5bb6ec76a7c6f5e2e6f386e96a3f24ee0036a728 100644 --- a/src/java.base/share/classes/java/util/regex/Pattern.java +++ b/src/java.base/share/classes/java/util/regex/Pattern.java @@ -396,7 +396,7 @@ import jdk.internal.util.ArraysSupport; *

      Backslashes within string literals in Java source code are interpreted * as required by * The Java Language Specification - * as either Unicode escapes (section {@jls 3.3}) or other character escapes (section {@jls 3.10.6}) + * as either Unicode escapes (section {@jls 3.3}) or other character escapes (section {@jls 3.10.6}). * It is therefore necessary to double backslashes in string * literals that represent regular expressions to protect them from * interpretation by the Java bytecode compiler. The string literal @@ -4005,8 +4005,9 @@ loop: for(int x=0, offset=0; x matcher.to) { + if (i + groupSizeChars > matcher.to) { matcher.hitEnd = true; return false; } @@ -5075,7 +5076,13 @@ loop: for(int x=0, offset=0; x= Character.MIN_SUPPLEMENTARY_CODE_POINT) { + //Group size is guessed in terms of chars, but we need to + //adjust if we spot a 2-char codePoint. + groupCodepoints--; + } } - return next.match(matcher, i+groupSize, seq); + return next.match(matcher, i+groupSizeChars, seq); } boolean study(TreeInfo info) { info.maxValid = false; diff --git a/src/java.base/share/classes/java/util/zip/Deflater.java b/src/java.base/share/classes/java/util/zip/Deflater.java index d41b8a7e12627f0e63937f7157aabc2aa01d9798..155264e4afe4b3940904febeb6103caad052054d 100644 --- a/src/java.base/share/classes/java/util/zip/Deflater.java +++ b/src/java.base/share/classes/java/util/zip/Deflater.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -895,6 +895,16 @@ public class Deflater { throw new NullPointerException("Deflater has been closed"); } + /** + * Returns the value of 'finish' flag. + * 'finish' will be set to true if def.finish() method is called. + */ + boolean shouldFinish() { + synchronized (zsRef) { + return finish; + } + } + private static native long init(int level, int strategy, boolean nowrap); private static native void setDictionary(long addr, byte[] b, int off, int len); diff --git a/src/java.base/share/classes/java/util/zip/DeflaterOutputStream.java b/src/java.base/share/classes/java/util/zip/DeflaterOutputStream.java index 7dfbd7f9edb5b4ef8644fa9f4fbfd825e31e7332..c856d8999b39f4bb6a88d0ef24da027f89042f3d 100644 --- a/src/java.base/share/classes/java/util/zip/DeflaterOutputStream.java +++ b/src/java.base/share/classes/java/util/zip/DeflaterOutputStream.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -220,9 +220,15 @@ public class DeflaterOutputStream extends FilterOutputStream { */ public void finish() throws IOException { if (!def.finished()) { - def.finish(); - while (!def.finished()) { - deflate(); + try{ + def.finish(); + while (!def.finished()) { + deflate(); + } + } catch(IOException e) { + if (usesDefaultDeflater) + def.end(); + throw e; } } } diff --git a/src/java.base/share/classes/java/util/zip/InflaterInputStream.java b/src/java.base/share/classes/java/util/zip/InflaterInputStream.java index e8ab2a449732cf786695fb185f74ff49089c0477..a87f78b38381cfece362bfd02845e61465132cb1 100644 --- a/src/java.base/share/classes/java/util/zip/InflaterInputStream.java +++ b/src/java.base/share/classes/java/util/zip/InflaterInputStream.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -150,7 +150,7 @@ public class InflaterInputStream extends FilterInputStream { } try { int n; - while ((n = inf.inflate(b, off, len)) == 0) { + do { if (inf.finished() || inf.needsDictionary()) { reachEOF = true; return -1; @@ -158,7 +158,7 @@ public class InflaterInputStream extends FilterInputStream { if (inf.needsInput()) { fill(); } - } + } while ((n = inf.inflate(b, off, len)) == 0); return n; } catch (DataFormatException e) { String s = e.getMessage(); @@ -189,8 +189,6 @@ public class InflaterInputStream extends FilterInputStream { } } - private byte[] b = new byte[512]; - /** * Skips specified number of bytes of uncompressed data. * @param n the number of bytes to skip @@ -205,6 +203,7 @@ public class InflaterInputStream extends FilterInputStream { ensureOpen(); int max = (int)Math.min(n, Integer.MAX_VALUE); int total = 0; + byte[] b = new byte[Math.min(max, 512)]; while (total < max) { int len = max - total; if (len > b.length) { diff --git a/src/java.base/share/classes/java/util/zip/ZipFile.java b/src/java.base/share/classes/java/util/zip/ZipFile.java index 1e5e92e4370cbe20159e0c7d1f13bb8ace37578b..8538b4aef89f4a5582f4f7f2b950f3f47b12bc35 100644 --- a/src/java.base/share/classes/java/util/zip/ZipFile.java +++ b/src/java.base/share/classes/java/util/zip/ZipFile.java @@ -345,7 +345,8 @@ public class ZipFile implements ZipConstants, Closeable { * * @param entry the zip file entry * @return the input stream for reading the contents of the specified - * zip file entry. + * zip file entry or null if the zip file entry does not exist + * within the zip file. * @throws ZipException if a ZIP format error has occurred * @throws IOException if an I/O error has occurred * @throws IllegalStateException if the zip file has been closed @@ -368,28 +369,28 @@ public class ZipFile implements ZipConstants, Closeable { } in = new ZipFileInputStream(zsrc.cen, pos); switch (CENHOW(zsrc.cen, pos)) { - case STORED: - synchronized (istreams) { - istreams.add(in); - } - return in; - case DEFLATED: - // Inflater likes a bit of slack - // MORE: Compute good size for inflater stream: - long size = CENLEN(zsrc.cen, pos) + 2; - if (size > 65536) { - size = 8192; - } - if (size <= 0) { - size = 4096; - } - InputStream is = new ZipFileInflaterInputStream(in, res, (int)size); - synchronized (istreams) { - istreams.add(is); - } - return is; - default: - throw new ZipException("invalid compression method"); + case STORED: + synchronized (istreams) { + istreams.add(in); + } + return in; + case DEFLATED: + // Inflater likes a bit of slack + // MORE: Compute good size for inflater stream: + long size = CENLEN(zsrc.cen, pos) + 2; + if (size > 65536) { + size = 8192; + } + if (size <= 0) { + size = 4096; + } + InputStream is = new ZipFileInflaterInputStream(in, res, (int) size); + synchronized (istreams) { + istreams.add(is); + } + return is; + default: + throw new ZipException("invalid compression method"); } } } @@ -1205,8 +1206,17 @@ public class ZipFile implements ZipConstants, Closeable { entries[index++] = hash; entries[index++] = next; entries[index ] = pos; + // Validate comment if it exists + // if the bytes representing the comment cannot be converted to + // a String via zcp.toString, an Exception will be thrown + int clen = CENCOM(cen, pos); + if (clen > 0) { + int elen = CENEXT(cen, pos); + int start = entryPos + nlen + elen; + zcp.toString(cen, start, clen); + } } catch (Exception e) { - zerror("invalid CEN header (bad entry name)"); + zerror("invalid CEN header (bad entry name or comment)"); } return nlen; } diff --git a/src/java.base/share/classes/java/util/zip/ZipOutputStream.java b/src/java.base/share/classes/java/util/zip/ZipOutputStream.java index 1b8ed562d9f7d0a5bd1f3f85a2acd37ab26695c1..d11eb4d4aae51032855b67994c7bb27389d6f757 100644 --- a/src/java.base/share/classes/java/util/zip/ZipOutputStream.java +++ b/src/java.base/share/classes/java/util/zip/ZipOutputStream.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2022, Oracle and/or its affiliates. All rights reserved. * 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,7 +314,7 @@ public class ZipOutputStream extends DeflaterOutputStream implements ZipConstant crc.reset(); current = null; } catch (IOException e) { - if (usesDefaultDeflater && !(e instanceof ZipException)) + if (def.shouldFinish() && usesDefaultDeflater && !(e instanceof ZipException)) def.end(); throw e; } diff --git a/src/java.base/share/classes/javax/net/SocketFactory.java b/src/java.base/share/classes/javax/net/SocketFactory.java index 5d56483b9de78701e246fca1252a89356eacc0cb..285167500b8e987999ef05e4438964a2d741c0fb 100644 --- a/src/java.base/share/classes/javax/net/SocketFactory.java +++ b/src/java.base/share/classes/javax/net/SocketFactory.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -120,12 +120,8 @@ public abstract class SocketFactory // The Exception is used by HttpsClient to signal that // unconnected sockets have not been implemented. // - UnsupportedOperationException uop = new - UnsupportedOperationException(); - SocketException se = new SocketException( - "Unconnected sockets not implemented"); - se.initCause(uop); - throw se; + throw new SocketException("Unconnected sockets not implemented", + new UnsupportedOperationException()); } diff --git a/src/java.base/share/classes/javax/net/ssl/SSLException.java b/src/java.base/share/classes/javax/net/ssl/SSLException.java index c77992db3014ff4793ffb32c56fd280bb0f38b1b..b2e96afa7d62860da2b36187250c2a4751f6d4dd 100644 --- a/src/java.base/share/classes/javax/net/ssl/SSLException.java +++ b/src/java.base/share/classes/javax/net/ssl/SSLException.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2022, Oracle and/or its affiliates. All rights reserved. * 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,9 +36,7 @@ import java.io.IOException; * @since 1.4 * @author David Brownell */ -public -class SSLException extends IOException -{ +public class SSLException extends IOException { @java.io.Serial private static final long serialVersionUID = 4511006460650708967L; @@ -48,8 +46,7 @@ class SSLException extends IOException * * @param reason describes the problem. */ - public SSLException(String reason) - { + public SSLException(String reason) { super(reason); } @@ -66,8 +63,7 @@ class SSLException extends IOException * @since 1.5 */ public SSLException(String message, Throwable cause) { - super(message); - initCause(cause); + super(message, cause); } /** @@ -83,7 +79,6 @@ class SSLException extends IOException * @since 1.5 */ public SSLException(Throwable cause) { - super(cause == null ? null : cause.toString()); - initCause(cause); + super(cause); } } diff --git a/src/java.base/share/classes/javax/net/ssl/SSLHandshakeException.java b/src/java.base/share/classes/javax/net/ssl/SSLHandshakeException.java index 5f342b074db855edfd00852777696abc5162810a..e6fa239bdcbbd0eae201a6a4f02580d55632dccc 100644 --- a/src/java.base/share/classes/javax/net/ssl/SSLHandshakeException.java +++ b/src/java.base/share/classes/javax/net/ssl/SSLHandshakeException.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,10 +23,8 @@ * questions. */ - package javax.net.ssl; - /** * Indicates that the client and server could not negotiate the * desired level of security. The connection is no longer usable. @@ -34,9 +32,7 @@ package javax.net.ssl; * @since 1.4 * @author David Brownell */ -public -class SSLHandshakeException extends SSLException -{ +public class SSLHandshakeException extends SSLException { @java.io.Serial private static final long serialVersionUID = -5045881315018326890L; @@ -46,8 +42,23 @@ class SSLHandshakeException extends SSLException * * @param reason describes the problem. */ - public SSLHandshakeException(String reason) - { + public SSLHandshakeException(String reason) { super(reason); } + + /** + * Creates a {@code SSLHandshakeException} with the specified detail + * message and cause. + * + * @param message the detail message (which is saved for later retrieval + * by the {@link #getMessage()} method). + * @param cause the cause (which is saved for later retrieval by the + * {@link #getCause()} method). (A {@code null} value is + * permitted, and indicates that the cause is nonexistent or + * unknown.) + * @since 19 + */ + public SSLHandshakeException(String message, Throwable cause) { + super(message, cause); + } } diff --git a/src/java.base/share/classes/javax/net/ssl/SSLKeyException.java b/src/java.base/share/classes/javax/net/ssl/SSLKeyException.java index 49fe57c369dbec171d40c38861a02bfa614bbf23..f27c9ee554c6f3156e446482eee9ab080222d42e 100644 --- a/src/java.base/share/classes/javax/net/ssl/SSLKeyException.java +++ b/src/java.base/share/classes/javax/net/ssl/SSLKeyException.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2022, Oracle and/or its affiliates. All rights reserved. * 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,9 +33,7 @@ package javax.net.ssl; * @since 1.4 * @author David Brownell */ -public -class SSLKeyException extends SSLException -{ +public class SSLKeyException extends SSLException { @java.io.Serial private static final long serialVersionUID = -8071664081941937874L; @@ -45,8 +43,23 @@ class SSLKeyException extends SSLException * * @param reason describes the problem. */ - public SSLKeyException(String reason) - { + public SSLKeyException(String reason) { super(reason); } + + /** + * Creates a {@code SSLKeyException} with the specified detail + * message and cause. + * + * @param message the detail message (which is saved for later retrieval + * by the {@link #getMessage()} method). + * @param cause the cause (which is saved for later retrieval by the + * {@link #getCause()} method). (A {@code null} value is + * permitted, and indicates that the cause is nonexistent or + * unknown.) + * @since 19 + */ + public SSLKeyException(String message, Throwable cause) { + super(message, cause); + } } diff --git a/src/java.base/share/classes/javax/net/ssl/SSLParameters.java b/src/java.base/share/classes/javax/net/ssl/SSLParameters.java index 5926c48aed083e6ddeedd7628760387b4f8ea8f3..b4fbdf9a437927d99617ee23b37f6c69c307058f 100644 --- a/src/java.base/share/classes/javax/net/ssl/SSLParameters.java +++ b/src/java.base/share/classes/javax/net/ssl/SSLParameters.java @@ -33,18 +33,20 @@ import java.util.*; * are the list of ciphersuites to be accepted in an SSL/TLS/DTLS handshake, * the list of protocols to be allowed, the endpoint identification * algorithm during SSL/TLS/DTLS handshaking, the Server Name Indication (SNI), - * the maximum network packet size, the algorithm constraints and whether - * SSL/TLS/DTLS servers should request or require client authentication, etc. + * the maximum network packet size, the algorithm constraints, the signature + * schemes and whether SSL/TLS/DTLS servers should request or require client + * authentication, etc. *

      - * SSLParameters can be created via the constructors in this class. - * Objects can also be obtained using the {@code getSSLParameters()} - * methods in + * {@code SSLParameter} objects can be created via the constructors in this + * class, and can be described as pre-populated objects. {@code SSLParameter} + * objects can also be obtained using the {@code getSSLParameters()} methods in * {@link SSLSocket#getSSLParameters SSLSocket} and * {@link SSLServerSocket#getSSLParameters SSLServerSocket} and * {@link SSLEngine#getSSLParameters SSLEngine} or the * {@link SSLContext#getDefaultSSLParameters getDefaultSSLParameters()} and * {@link SSLContext#getSupportedSSLParameters getSupportedSSLParameters()} - * methods in {@code SSLContext}. + * methods in {@code SSLContext}, and can be described as connection populated + * objects. *

      * SSLParameters can be applied to a connection via the methods * {@link SSLSocket#setSSLParameters SSLSocket.setSSLParameters()} and @@ -82,16 +84,17 @@ public class SSLParameters { private boolean enableRetransmissions = true; private int maximumPacketSize = 0; private String[] applicationProtocols = new String[0]; + private String[] signatureSchemes = null; /** * Constructs SSLParameters. *

      * The values of cipherSuites, protocols, cryptographic algorithm - * constraints, endpoint identification algorithm, server names and - * server name matchers are set to {@code null}; useCipherSuitesOrder, - * wantClientAuth and needClientAuth are set to {@code false}; - * enableRetransmissions is set to {@code true}; maximum network packet - * size is set to {@code 0}. + * constraints, endpoint identification algorithm, signature schemes, + * server names and server name matchers are set to {@code null}; + * useCipherSuitesOrder, wantClientAuth and needClientAuth are set + * to {@code false}; enableRetransmissions is set to {@code true}; + * maximum network packet size is set to {@code 0}. */ public SSLParameters() { // empty @@ -367,7 +370,7 @@ public class SSLParameters { *

      * It is recommended that providers initialize default Server Name * Indications when creating {@code SSLSocket}/{@code SSLEngine}s. - * In the following examples, the server name could be represented by an + * In the following examples, the server name may be represented by an * instance of {@link SNIHostName} which has been initialized with the * hostname "www.example.com" and type * {@link StandardConstants#SNI_HOST_NAME}. @@ -686,4 +689,125 @@ public class SSLParameters { } applicationProtocols = tempProtocols; } + + /** + * Returns a prioritized array of signature scheme names that can be used + * over the SSL/TLS/DTLS protocols. + *

      + * Note that the standard list of signature scheme names are defined in + * the + * Signature Schemes section of the Java Security Standard Algorithm + * Names Specification. Providers may support signature schemes not defined + * in this list or may not use the recommended name for a certain + * signature scheme. + *

      + * The set of signature schemes that will be used over the SSL/TLS/DTLS + * connections is determined by the returned array of this method and the + * underlying provider-specific default signature schemes. + *

      + * If the returned array is {@code null}, then the underlying + * provider-specific default signature schemes will be used over the + * SSL/TLS/DTLS connections. + *

      + * If the returned array is empty (zero-length), then the signature scheme + * negotiation mechanism is turned off for SSL/TLS/DTLS protocols, and + * the connections may not be able to be established if the negotiation + * mechanism is required by a certain SSL/TLS/DTLS protocol. This + * parameter will override the underlying provider-specific default + * signature schemes. + *

      + * If the returned array is not {@code null} or empty (zero-length), + * then the signature schemes in the returned array will be used over + * the SSL/TLS/DTLS connections. This parameter will override the + * underlying provider-specific default signature schemes. + *

      + * This method returns the most recent value passed to + * {@link #setSignatureSchemes} if that method has been called and + * otherwise returns the default signature schemes for connection + * populated objects, or {@code null} for pre-populated objects. + * + * @apiNote + * Note that a provider may not have been updated to support this method + * and in that case may return {@code null} instead of the default + * signature schemes for connection populated objects. + * + * @implNote + * The SunJSSE provider supports this method. + * + * @implNote + * Note that applications may use the + * {@systemProperty jdk.tls.client.SignatureSchemes} and/or + * {@systemProperty jdk.tls.server.SignatureSchemes} system properties + * with the SunJSSE provider to override the provider-specific default + * signature schemes. + * + * @return an array of signature scheme {@code Strings} or {@code null} if + * none have been set. For non-null returns, this method will + * return a new array each time it is invoked. The array is + * ordered based on signature scheme preference, with the first + * entry being the most preferred. Providers should ignore unknown + * signature scheme names while establishing the SSL/TLS/DTLS + * connections. + * @see #setSignatureSchemes + * + * @since 19 + */ + public String[] getSignatureSchemes() { + return clone(signatureSchemes); + } + + /** + * Sets the prioritized array of signature scheme names that + * can be used over the SSL/TLS/DTLS protocols. + *

      + * Note that the standard list of signature scheme names are defined in + * the + * Signature Schemes section of the Java Security Standard Algorithm + * Names Specification. Providers may support signature schemes not + * defined in this list or may not use the recommended name for a certain + * signature scheme. + *

      + * The set of signature schemes that will be used over the SSL/TLS/DTLS + * connections is determined by the input parameter {@code signatureSchemes} + * array and the underlying provider-specific default signature schemes. + * See {@link #getSignatureSchemes} for specific details on how the + * parameters are used in SSL/TLS/DTLS connections. + * + * @apiNote + * Note that a provider may not have been updated to support this method + * and in that case may ignore the schemes that are set. + * + * @implNote + * The SunJSSE provider supports this method. + * + * @param signatureSchemes an ordered array of signature scheme names with + * the first entry being the most preferred, or {@code null}. This + * method will make a copy of this array. Providers should ignore + * unknown signature scheme names while establishing the + * SSL/TLS/DTLS connections. + * @throws IllegalArgumentException if any element in the + * {@code signatureSchemes} array is {@code null} or + * {@linkplain String#isBlank() blank}. + * + * @see #getSignatureSchemes + * + * @since 19 + */ + public void setSignatureSchemes(String[] signatureSchemes) { + String[] tempSchemes = null; + + if (signatureSchemes != null) { + tempSchemes = signatureSchemes.clone(); + for (String scheme : tempSchemes) { + if (scheme == null || scheme.isBlank()) { + throw new IllegalArgumentException( + "An element of signatureSchemes is null or blank"); + } + } + } + + this.signatureSchemes = tempSchemes; + } } diff --git a/src/java.base/share/classes/javax/net/ssl/SSLPeerUnverifiedException.java b/src/java.base/share/classes/javax/net/ssl/SSLPeerUnverifiedException.java index e98e2b4b7f46b6cef6dcddd4f42ea9473bf20d90..3fbec6c04345a24a8167cc4ebf928abc674437ae 100644 --- a/src/java.base/share/classes/javax/net/ssl/SSLPeerUnverifiedException.java +++ b/src/java.base/share/classes/javax/net/ssl/SSLPeerUnverifiedException.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2022, Oracle and/or its affiliates. All rights reserved. * 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,9 +39,7 @@ package javax.net.ssl; * @since 1.4 * @author David Brownell */ -public -class SSLPeerUnverifiedException extends SSLException -{ +public class SSLPeerUnverifiedException extends SSLException { @java.io.Serial private static final long serialVersionUID = -8919512675000600547L; @@ -51,8 +49,23 @@ class SSLPeerUnverifiedException extends SSLException * * @param reason describes the problem. */ - public SSLPeerUnverifiedException(String reason) - { + public SSLPeerUnverifiedException(String reason) { super(reason); } + + /** + * Creates a {@code SSLPeerUnverifiedException} with the specified detail + * message and cause. + * + * @param message the detail message (which is saved for later retrieval + * by the {@link #getMessage()} method). + * @param cause the cause (which is saved for later retrieval by the + * {@link #getCause()} method). (A {@code null} value is + * permitted, and indicates that the cause is nonexistent or + * unknown.) + * @since 19 + */ + public SSLPeerUnverifiedException(String message, Throwable cause) { + super(message, cause); + } } diff --git a/src/java.base/share/classes/javax/net/ssl/SSLProtocolException.java b/src/java.base/share/classes/javax/net/ssl/SSLProtocolException.java index a39b2048924977dfcf382462d59dccb457895c82..bf590430b3fffc8378149048b364871fe29e81d5 100644 --- a/src/java.base/share/classes/javax/net/ssl/SSLProtocolException.java +++ b/src/java.base/share/classes/javax/net/ssl/SSLProtocolException.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2022, Oracle and/or its affiliates. All rights reserved. * 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,9 +33,7 @@ package javax.net.ssl; * @since 1.4 * @author David Brownell */ -public -class SSLProtocolException extends SSLException -{ +public class SSLProtocolException extends SSLException { @java.io.Serial private static final long serialVersionUID = 5445067063799134928L; @@ -45,8 +43,23 @@ class SSLProtocolException extends SSLException * * @param reason describes the problem. */ - public SSLProtocolException(String reason) - { + public SSLProtocolException(String reason) { super(reason); } + + /** + * Creates a {@code SSLProtocolException} with the specified detail + * message and cause. + * + * @param message the detail message (which is saved for later retrieval + * by the {@link #getMessage()} method). + * @param cause the cause (which is saved for later retrieval by the + * {@link #getCause()} method). (A {@code null} value is + * permitted, and indicates that the cause is nonexistent or + * unknown.) + * @since 19 + */ + public SSLProtocolException(String message, Throwable cause) { + super(message, cause); + } } diff --git a/src/java.base/share/classes/javax/net/ssl/SSLServerSocketFactory.java b/src/java.base/share/classes/javax/net/ssl/SSLServerSocketFactory.java index 68c09c02a6f6c9939a145a415374f4a0a4461dcf..22f64f98f29fce57193e2c2153f8ae1e1dc5929a 100644 --- a/src/java.base/share/classes/javax/net/ssl/SSLServerSocketFactory.java +++ b/src/java.base/share/classes/javax/net/ssl/SSLServerSocketFactory.java @@ -173,8 +173,7 @@ class DefaultSSLServerSocketFactory extends SSLServerSocketFactory { } private ServerSocket throwException() throws SocketException { - throw (SocketException) - new SocketException(reason.toString()).initCause(reason); + throw new SocketException(reason.toString(), reason); } @Override diff --git a/src/java.base/share/classes/javax/net/ssl/SSLSocket.java b/src/java.base/share/classes/javax/net/ssl/SSLSocket.java index b2c912c3b65bdf2bff1c074ef51d1fdbeaefc969..e5cdd3741b944ab2eebff261240458dd376e7736 100644 --- a/src/java.base/share/classes/javax/net/ssl/SSLSocket.java +++ b/src/java.base/share/classes/javax/net/ssl/SSLSocket.java @@ -174,17 +174,19 @@ import java.util.function.BiFunction; * @apiNote * When the connection is no longer needed, the client and server * applications should each close both sides of their respective connection. - * For {@code SSLSocket} objects, for example, an application can call - * {@link Socket#shutdownOutput()} or {@link java.io.OutputStream#close()} - * for output stream close and call {@link Socket#shutdownInput()} or - * {@link java.io.InputStream#close()} for input stream close. Note that - * in some cases, closing the input stream may depend on the peer's output - * stream being closed first. If the connection is not closed in an orderly - * manner (for example {@link Socket#shutdownInput()} is called before the - * peer's write closure notification has been received), exceptions may - * be raised to indicate that an error has occurred. Once an - * {@code SSLSocket} is closed, it is not reusable: a new {@code SSLSocket} - * must be created. + * This can be done either in one shot by calling {@link Socket#close()}, + * or by closing each side individually using + * {@link Socket#shutdownOutput()} / {@link Socket#shutdownInput()} which is + * useful for protocol versions that can support half-closed connections. + * + *

      Note that in some cases, closing the input stream may depend on the + * peer's output stream being closed first. If the connection is not closed + * in an orderly manner (for example {@link Socket#shutdownInput()} is called + * before the peer's write closure notification has been received), exceptions + * may be raised to indicate that an error has occurred. + * + *

      Once an {@code SSLSocket} is closed, it is not reusable: a new + * {@code SSLSocket} must be created. * * @see java.net.Socket * @see SSLServerSocket diff --git a/src/java.base/share/classes/javax/net/ssl/SSLSocketFactory.java b/src/java.base/share/classes/javax/net/ssl/SSLSocketFactory.java index dd10f422f3ece59a19e351ad8ad787868b2b49ab..6a01687dc56fb004b7751b3a421174ec3a09f49c 100644 --- a/src/java.base/share/classes/javax/net/ssl/SSLSocketFactory.java +++ b/src/java.base/share/classes/javax/net/ssl/SSLSocketFactory.java @@ -263,8 +263,7 @@ class DefaultSSLSocketFactory extends SSLSocketFactory } private Socket throwException() throws SocketException { - throw (SocketException) - new SocketException(reason.toString()).initCause(reason); + throw new SocketException(reason.toString(), reason); } @Override diff --git a/src/java.base/share/classes/jdk/internal/loader/NativeLibraries.java b/src/java.base/share/classes/jdk/internal/loader/NativeLibraries.java index b10c7de434d6d1081a322f5070801588d1b2f032..c5ede021e00bfaee3c27fd8d122c18649c92a9e3 100644 --- a/src/java.base/share/classes/jdk/internal/loader/NativeLibraries.java +++ b/src/java.base/share/classes/jdk/internal/loader/NativeLibraries.java @@ -190,7 +190,7 @@ public final class NativeLibraries { } } - NativeLibraryImpl lib = new NativeLibraryImpl(fromClass, name, isBuiltin, true); + NativeLibraryImpl lib = new NativeLibraryImpl(fromClass, name, isBuiltin); // load the native library NativeLibraryContext.push(lib); try { @@ -281,7 +281,7 @@ public final class NativeLibraries { * the VM when it loads the library, and used by the VM to pass the correct * version of JNI to the native methods. */ - static class NativeLibraryImpl implements NativeLibrary { + static class NativeLibraryImpl extends NativeLibrary { // the class from which the library is loaded, also indicates // the loader this native library belongs. final Class fromClass; @@ -290,21 +290,16 @@ public final class NativeLibraries { final String name; // Indicates if the native library is linked into the VM final boolean isBuiltin; - // Indicate if this is JNI native library - final boolean isJNI; // opaque handle to native library, used in native code. long handle; // the version of JNI environment the native library requires. int jniVersion; - NativeLibraryImpl(Class fromClass, String name, boolean isBuiltin, boolean isJNI) { - assert !isBuiltin || isJNI : "a builtin native library must be JNI library"; - + NativeLibraryImpl(Class fromClass, String name, boolean isBuiltin) { this.fromClass = fromClass; this.name = name; this.isBuiltin = isBuiltin; - this.isJNI = isJNI; } @Override @@ -314,7 +309,7 @@ public final class NativeLibraries { @Override public long find(String name) { - return findEntry0(this, name); + return findEntry0(handle, name); } /* @@ -322,7 +317,7 @@ public final class NativeLibraries { * when this class loader becomes phantom reachable. */ private Runnable unloader() { - return new Unloader(name, handle, isBuiltin, isJNI); + return new Unloader(name, handle, isBuiltin); } /* @@ -333,14 +328,14 @@ public final class NativeLibraries { throw new InternalError("Native library " + name + " has been loaded"); } - return load(this, name, isBuiltin, isJNI, loadLibraryOnlyIfPresent); + return load(this, name, isBuiltin, loadLibraryOnlyIfPresent); } /* * Close this native library. */ void close() { - unload(name, isBuiltin, isJNI, handle); + unload(name, isBuiltin, handle); } } @@ -352,15 +347,13 @@ public final class NativeLibraries { // This represents the context when a native library is unloaded // and getFromClass() will return null, static final NativeLibraryImpl UNLOADER = - new NativeLibraryImpl(null, "dummy", false, false); + new NativeLibraryImpl(null, "dummy", false); final String name; final long handle; final boolean isBuiltin; - final boolean isJNI; - Unloader(String name, long handle, boolean isBuiltin, boolean isJNI) { - assert !isBuiltin || isJNI : "a builtin native library must be JNI library"; + Unloader(String name, long handle, boolean isBuiltin) { if (handle == 0) { throw new IllegalArgumentException( "Invalid handle for native library " + name); @@ -369,7 +362,6 @@ public final class NativeLibraries { this.name = name; this.handle = handle; this.isBuiltin = isBuiltin; - this.isJNI = isJNI; } @Override @@ -377,12 +369,12 @@ public final class NativeLibraries { acquireNativeLibraryLock(name); try { /* remove the native library name */ - if (isJNI && !loadedLibraryNames.remove(name)) { + if (!loadedLibraryNames.remove(name)) { throw new IllegalStateException(name + " has already been unloaded"); } NativeLibraryContext.push(UNLOADER); try { - unload(name, isBuiltin, isJNI, handle); + unload(name, isBuiltin, handle); } finally { NativeLibraryContext.pop(); } @@ -524,12 +516,22 @@ public final class NativeLibraries { return NativeLibraryContext.peek().fromClass; } - // JNI FindClass expects the caller class if invoked from JNI_OnLoad - // and JNI_OnUnload is NativeLibrary class + /* + * Return true if the given library is successfully loaded. + * If the given library cannot be loaded for any reason, + * if throwExceptionIfFail is false, then this method returns false; + * otherwise, UnsatisfiedLinkError will be thrown. + * + * JNI FindClass expects the caller class if invoked from JNI_OnLoad + * and JNI_OnUnload is NativeLibrary class. + */ private static native boolean load(NativeLibraryImpl impl, String name, - boolean isBuiltin, boolean isJNI, + boolean isBuiltin, boolean throwExceptionIfFail); - private static native void unload(String name, boolean isBuiltin, boolean isJNI, long handle); + /* + * Unload the named library. JNI_OnUnload, if present, will be invoked + * before the native library is unloaded. + */ + private static native void unload(String name, boolean isBuiltin, long handle); private static native String findBuiltinLib(String name); - private static native long findEntry0(NativeLibraryImpl lib, String name); } diff --git a/src/java.base/share/classes/jdk/internal/loader/NativeLibrary.java b/src/java.base/share/classes/jdk/internal/loader/NativeLibrary.java index 2b684e0bf357c70cea38109f2637561f8c04ca55..228356e0773b3409def0b85a4df8b2a4bf9e031f 100644 --- a/src/java.base/share/classes/jdk/internal/loader/NativeLibrary.java +++ b/src/java.base/share/classes/jdk/internal/loader/NativeLibrary.java @@ -28,8 +28,8 @@ package jdk.internal.loader; /** * NativeLibrary represents a loaded native library instance. */ -public interface NativeLibrary { - String name(); +public abstract class NativeLibrary { + public abstract String name(); /** * Finds the address of the entry of the given name. Returns 0 @@ -37,7 +37,7 @@ public interface NativeLibrary { * * @param name the name of the symbol to be found */ - long find(String name); + public abstract long find(String name); /** * Finds the address of the entry of the given name. @@ -45,11 +45,17 @@ public interface NativeLibrary { * @param name the name of the symbol to be found * @throws NoSuchMethodException if the named entry is not found. */ - default long lookup(String name) throws NoSuchMethodException { + public final long lookup(String name) throws NoSuchMethodException { long addr = find(name); if (0 == addr) { throw new NoSuchMethodException("Cannot find symbol " + name + " in library " + name()); } return addr; } + + /* + * Returns the address of the named symbol defined in the library of + * the given handle. Returns 0 if not found. + */ + static native long findEntry0(long handle, String name); } diff --git a/src/java.base/share/classes/jdk/internal/loader/RawNativeLibraries.java b/src/java.base/share/classes/jdk/internal/loader/RawNativeLibraries.java index 182f442dd5e57c6d7c52913db37b82c61ff4a56c..972e34e1fd20b94a33ded6d6839f5c727154ba62 100644 --- a/src/java.base/share/classes/jdk/internal/loader/RawNativeLibraries.java +++ b/src/java.base/share/classes/jdk/internal/loader/RawNativeLibraries.java @@ -35,9 +35,6 @@ import java.util.Map; import java.util.Objects; import java.util.concurrent.ConcurrentHashMap; -import static jdk.internal.loader.NativeLibraries.*; - - /** * RawNativeLibraries has the following properties: * 1. Native libraries loaded in this RawNativeLibraries instance are @@ -48,7 +45,7 @@ import static jdk.internal.loader.NativeLibraries.*; * 3. No relationship with class loaders. */ public final class RawNativeLibraries { - final Map libraries = new ConcurrentHashMap<>(); + final Map libraries = new ConcurrentHashMap<>(); final Class caller; private RawNativeLibraries(MethodHandles.Lookup trustedCaller) { @@ -116,10 +113,10 @@ public final class RawNativeLibraries { return libraries.computeIfAbsent(pathname, this::get); } - private NativeLibraryImpl get(String pathname) { - NativeLibraryImpl lib = new NativeLibraryImpl(caller, pathname, false, false); + private RawNativeLibraryImpl get(String pathname) { + RawNativeLibraryImpl lib = new RawNativeLibraryImpl(caller, pathname); if (!lib.open()) { - return null; // fail to open the native library + return null; } return lib; } @@ -132,8 +129,49 @@ public final class RawNativeLibraries { if (!libraries.remove(lib.name(), lib)) { throw new IllegalArgumentException(lib.name() + " not loaded by this RawNativeLibraries instance"); } - NativeLibraryImpl nl = (NativeLibraryImpl)lib; + RawNativeLibraryImpl nl = (RawNativeLibraryImpl)lib; nl.close(); } + + static class RawNativeLibraryImpl extends NativeLibrary { + // the name of the raw native library. + final String name; + // opaque handle to raw native library, used in native code. + long handle; + + RawNativeLibraryImpl(Class fromClass, String name) { + this.name = name; + } + + @Override + public String name() { + return name; + } + + @Override + public long find(String name) { + return findEntry0(handle, name); + } + + /* + * Loads the named native library. + */ + boolean open() { + if (handle != 0) { + throw new InternalError("Native library " + name + " has been loaded"); + } + return load0(this, name); + } + + /* + * Close this native library. + */ + void close() { + unload0(name, handle); + } + } + + private static native boolean load0(RawNativeLibraryImpl impl, String name); + private static native void unload0(String name, long handle); } diff --git a/src/java.base/share/classes/jdk/internal/logger/LoggerFinderLoader.java b/src/java.base/share/classes/jdk/internal/logger/LoggerFinderLoader.java index dbf4ccca128e4c292231f66fd1e3f33f11296cd3..4f009973e2742a2468aa2437353f23bcd178a99a 100644 --- a/src/java.base/share/classes/jdk/internal/logger/LoggerFinderLoader.java +++ b/src/java.base/share/classes/jdk/internal/logger/LoggerFinderLoader.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 @@ -129,7 +129,7 @@ public final class LoggerFinderLoader { result = iterator.next(); if (iterator.hasNext() && ensureSingletonProvider()) { throw new ServiceConfigurationError( - "More than on LoggerFinder implementation"); + "More than one LoggerFinder implementation"); } } else { result = loadDefaultImplementation(); diff --git a/src/java.base/share/classes/jdk/internal/module/ModulePath.java b/src/java.base/share/classes/jdk/internal/module/ModulePath.java index 876050ef8396851544d4ca7a202ef79d6388f606..3bce921cfe74c9aeee5c3b64309748577af4e9b9 100644 --- a/src/java.base/share/classes/jdk/internal/module/ModulePath.java +++ b/src/java.base/share/classes/jdk/internal/module/ModulePath.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2021, 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 @@ -662,11 +662,12 @@ public class ModulePath implements ModuleFinder { // -- exploded directories -- private Set explodedPackages(Path dir) { + String separator = dir.getFileSystem().getSeparator(); try { return Files.find(dir, Integer.MAX_VALUE, ((path, attrs) -> attrs.isRegularFile() && !isHidden(path))) .map(path -> dir.relativize(path)) - .map(this::toPackageName) + .map(path -> toPackageName(path, separator)) .flatMap(Optional::stream) .collect(Collectors.toSet()); } catch (IOException x) { @@ -737,7 +738,7 @@ public class ModulePath implements ModuleFinder { * @throws InvalidModuleDescriptorException if the name is a class file in * the top-level directory (and it's not module-info.class) */ - private Optional toPackageName(Path file) { + private Optional toPackageName(Path file, String separator) { assert file.getRoot() == null; Path parent = file.getParent(); @@ -751,7 +752,7 @@ public class ModulePath implements ModuleFinder { return Optional.empty(); } - String pn = parent.toString().replace(File.separatorChar, '.'); + String pn = parent.toString().replace(separator, "."); if (Checks.isPackageName(pn)) { return Optional.of(pn); } else { diff --git a/src/java.base/share/classes/jdk/internal/reflect/ReflectionFactory.java b/src/java.base/share/classes/jdk/internal/reflect/ReflectionFactory.java index ee264330d2ba89bb4a5b28f012622c2eaa666d8e..20de7a6bc84168b9bddc50372ba3addf97b591dc 100644 --- a/src/java.base/share/classes/jdk/internal/reflect/ReflectionFactory.java +++ b/src/java.base/share/classes/jdk/internal/reflect/ReflectionFactory.java @@ -44,6 +44,7 @@ import java.util.Properties; import jdk.internal.access.JavaLangReflectAccess; import jdk.internal.access.SharedSecrets; import jdk.internal.misc.VM; +import jdk.internal.vm.annotation.Stable; import sun.security.action.GetPropertyAction; import sun.security.util.SecurityConstants; @@ -61,42 +62,12 @@ import sun.security.util.SecurityConstants; public class ReflectionFactory { - private static boolean initted = false; private static final ReflectionFactory soleInstance = new ReflectionFactory(); /* Method for static class initializer , or null */ private static volatile Method hasStaticInitializerMethod; - // - // "Inflation" mechanism. Loading bytecodes to implement - // Method.invoke() and Constructor.newInstance() currently costs - // 3-4x more than an invocation via native code for the first - // invocation (though subsequent invocations have been benchmarked - // to be over 20x faster). Unfortunately this cost increases - // startup time for certain applications that use reflection - // intensively (but only once per class) to bootstrap themselves. - // To avoid this penalty we reuse the existing JVM entry points - // for the first few invocations of Methods and Constructors and - // then switch to the bytecode-based implementations. - // - // Package-private to be accessible to NativeMethodAccessorImpl - // and NativeConstructorAccessorImpl - private static boolean noInflation = false; - private static int inflationThreshold = 15; - - // - // New implementation uses direct invocation of method handles - private static final int METHOD_MH_ACCESSOR = 0x1; - private static final int FIELD_MH_ACCESSOR = 0x2; - private static final int ALL_MH_ACCESSORS = METHOD_MH_ACCESSOR|FIELD_MH_ACCESSOR; - - private static int useDirectMethodHandle = ALL_MH_ACCESSORS; - private static boolean useNativeAccessorOnly = false; // for testing only - - // true if deserialization constructor checking is disabled - private static boolean disableSerialConstructorChecks = false; - private final JavaLangReflectAccess langReflectAccess; private ReflectionFactory() { this.langReflectAccess = SharedSecrets.getJavaLangReflectAccess(); @@ -160,8 +131,6 @@ public class ReflectionFactory { * @param override true if caller has overridden accessibility */ public FieldAccessor newFieldAccessor(Field field, boolean override) { - checkInitted(); - Field root = langReflectAccess.getRoot(field); if (root != null) { // FieldAccessor will use the root unless the modifiers have @@ -180,8 +149,6 @@ public class ReflectionFactory { } public MethodAccessor newMethodAccessor(Method method, boolean callerSensitive) { - checkInitted(); - // use the root Method that will not cache caller class Method root = langReflectAccess.getRoot(method); if (root != null) { @@ -191,7 +158,7 @@ public class ReflectionFactory { if (useMethodHandleAccessor()) { return MethodHandleAccessorFactory.newMethodAccessor(method, callerSensitive); } else { - if (noInflation && !method.getDeclaringClass().isHidden()) { + if (noInflation() && !method.getDeclaringClass().isHidden()) { return generateMethodAccessor(method); } else { NativeMethodAccessorImpl acc = new NativeMethodAccessorImpl(method); @@ -215,8 +182,6 @@ public class ReflectionFactory { } public ConstructorAccessor newConstructorAccessor(Constructor c) { - checkInitted(); - Class declaringClass = c.getDeclaringClass(); if (Modifier.isAbstract(declaringClass.getModifiers())) { return new InstantiationExceptionConstructorAccessorImpl(null); @@ -242,7 +207,7 @@ public class ReflectionFactory { return new BootstrapConstructorAccessorImpl(c); } - if (noInflation && !c.getDeclaringClass().isHidden()) { + if (noInflation() && !c.getDeclaringClass().isHidden()) { return new MethodAccessorGenerator(). generateConstructor(c.getDeclaringClass(), c.getParameterTypes(), @@ -430,7 +395,7 @@ public class ReflectionFactory { while (Serializable.class.isAssignableFrom(initCl)) { Class prev = initCl; if ((initCl = initCl.getSuperclass()) == null || - (!disableSerialConstructorChecks && !superHasAccessibleConstructor(prev))) { + (!disableSerialConstructorChecks() && !superHasAccessibleConstructor(prev))) { return null; } } @@ -623,41 +588,108 @@ public class ReflectionFactory { // Internals only below this point // + // Package-private to be accessible to NativeMethodAccessorImpl + // and NativeConstructorAccessorImpl static int inflationThreshold() { - return inflationThreshold; + return config().inflationThreshold; } static boolean noInflation() { - return noInflation; + return config().noInflation; } static boolean useMethodHandleAccessor() { - return (useDirectMethodHandle & METHOD_MH_ACCESSOR) == METHOD_MH_ACCESSOR; + return (config().useDirectMethodHandle & METHOD_MH_ACCESSOR) == METHOD_MH_ACCESSOR; } static boolean useFieldHandleAccessor() { - return (useDirectMethodHandle & FIELD_MH_ACCESSOR) == FIELD_MH_ACCESSOR; + return (config().useDirectMethodHandle & FIELD_MH_ACCESSOR) == FIELD_MH_ACCESSOR; } static boolean useNativeAccessorOnly() { - return useNativeAccessorOnly; + return config().useNativeAccessorOnly; } - /** We have to defer full initialization of this class until after - the static initializer is run since java.lang.reflect.Method's - static initializer (more properly, that for - java.lang.reflect.AccessibleObject) causes this class's to be - run, before the system properties are set up. */ - private static void checkInitted() { - if (initted) return; + private static boolean disableSerialConstructorChecks() { + return config().disableSerialConstructorChecks; + } + + // New implementation uses direct invocation of method handles + private static final int METHOD_MH_ACCESSOR = 0x1; + private static final int FIELD_MH_ACCESSOR = 0x2; + private static final int ALL_MH_ACCESSORS = METHOD_MH_ACCESSOR | FIELD_MH_ACCESSOR; + + /** + * The configuration is lazily initialized after the module system is initialized. The + * default config would be used before the proper config is loaded. + * + * The static initializer of ReflectionFactory is run before the system properties are set up. + * The class initialization is caused by the class initialization of java.lang.reflect.Method + * (more properly, caused by the class initialization for java.lang.reflect.AccessibleObject) + * that happens very early VM startup, initPhase1. + */ + private static @Stable Config config; + + // "Inflation" mechanism. Loading bytecodes to implement + // Method.invoke() and Constructor.newInstance() currently costs + // 3-4x more than an invocation via native code for the first + // invocation (though subsequent invocations have been benchmarked + // to be over 20x faster). Unfortunately this cost increases + // startup time for certain applications that use reflection + // intensively (but only once per class) to bootstrap themselves. + // To avoid this penalty we reuse the existing JVM entry points + // for the first few invocations of Methods and Constructors and + // then switch to the bytecode-based implementations. + + private static final Config DEFAULT_CONFIG = new Config(false, // noInflation + 15, // inflationThreshold + ALL_MH_ACCESSORS, // useDirectMethodHandle + false, // useNativeAccessorOnly + false); // disableSerialConstructorChecks + + /** + * The configurations for the reflection factory. Configurable via + * system properties but only available after ReflectionFactory is + * loaded during early VM startup. + * + * Note that the default implementations of the object methods of + * this Config record (toString, equals, hashCode) use indy, + * which is available to use only after initPhase1. These methods + * are currently not called, but should they be needed, a workaround + * is to override them. + */ + private record Config(boolean noInflation, + int inflationThreshold, + int useDirectMethodHandle, + boolean useNativeAccessorOnly, + boolean disableSerialConstructorChecks) { + } + + private static Config config() { + Config c = config; + if (c != null) { + return c; + } // Defer initialization until module system is initialized so as // to avoid inflation and spinning bytecode in unnamed modules // during early startup. if (!VM.isModuleSystemInited()) { - return; + return DEFAULT_CONFIG; } + return config = loadConfig(); + } + + private static Config loadConfig() { + assert VM.isModuleSystemInited(); + + boolean noInflation = DEFAULT_CONFIG.noInflation; + int inflationThreshold = DEFAULT_CONFIG.inflationThreshold; + int useDirectMethodHandle = DEFAULT_CONFIG.useDirectMethodHandle; + boolean useNativeAccessorOnly = DEFAULT_CONFIG.useNativeAccessorOnly; + boolean disableSerialConstructorChecks = DEFAULT_CONFIG.disableSerialConstructorChecks; + Properties props = GetPropertyAction.privilegedGetProperties(); String val = props.getProperty("sun.reflect.noInflation"); if (val != null && val.equals("true")) { @@ -690,7 +722,11 @@ public class ReflectionFactory { disableSerialConstructorChecks = "true".equals(props.getProperty("jdk.disableSerialConstructorChecks")); - initted = true; + return new Config(noInflation, + inflationThreshold, + useDirectMethodHandle, + useNativeAccessorOnly, + disableSerialConstructorChecks); } /** diff --git a/src/java.base/share/classes/jdk/internal/util/random/RandomSupport.java b/src/java.base/share/classes/jdk/internal/util/random/RandomSupport.java index 1fc1eeff46a03e9d5da84fd94a0aeb3b23803d88..24a73f734d3ceb0b368051fd20811e05be2ef846 100644 --- a/src/java.base/share/classes/jdk/internal/util/random/RandomSupport.java +++ b/src/java.base/share/classes/jdk/internal/util/random/RandomSupport.java @@ -265,7 +265,7 @@ public class RandomSupport { final int m = Math.min(seed.length, n << 3); // Distribute seed bytes into the words to be formed. for (int j = 0; j < m; j++) { - result[j>>3] = (result[j>>3] << 8) | seed[j]; + result[j>>3] = (result[j>>3] << 8) | (seed[j] & 0xFF); } // If there aren't enough seed bytes for all the words we need, // use a SplitMix-style PRNG to fill in the rest. diff --git a/src/java.base/share/classes/sun/net/www/protocol/https/AbstractDelegateHttpsURLConnection.java b/src/java.base/share/classes/sun/net/www/protocol/https/AbstractDelegateHttpsURLConnection.java index 7ed4381dda6e6c231fb2542a7694beacbf8ab120..ff54e474b8e696d2b93c0ff6e13f103617e2ff0b 100644 --- a/src/java.base/share/classes/sun/net/www/protocol/https/AbstractDelegateHttpsURLConnection.java +++ b/src/java.base/share/classes/sun/net/www/protocol/https/AbstractDelegateHttpsURLConnection.java @@ -332,10 +332,11 @@ public abstract class AbstractDelegateHttpsURLConnection extends if (prop.startsWith("domain:")) { String[] domains = prop.substring(7).split(","); for (String domain : domains) { - if (target.equals(domain)) { + if (target.equalsIgnoreCase(domain)) { return true; } - if (domain.startsWith("*.") && target.endsWith(domain.substring(1))) { + if (domain.startsWith("*.") && target.regionMatches( + true, target.length() - domain.length() + 1, domain, 1, domain.length() - 1)) { return true; } } diff --git a/src/java.base/share/classes/sun/net/www/protocol/https/HttpsClient.java b/src/java.base/share/classes/sun/net/www/protocol/https/HttpsClient.java index 4818f945bcc15f03954163bc1cff29247c4e8f27..1cb435f7fdfe0885eafc883b4e439299bc82d845 100644 --- a/src/java.base/share/classes/sun/net/www/protocol/https/HttpsClient.java +++ b/src/java.base/share/classes/sun/net/www/protocol/https/HttpsClient.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 @@ -661,12 +661,17 @@ final class HttpsClient extends HttpClient @Override protected void putInKeepAliveCache() { - if (inCache) { - assert false : "Duplicate put to keep alive cache"; - return; + lock(); + try { + if (inCache) { + assert false : "Duplicate put to keep alive cache"; + return; + } + inCache = true; + kac.put(url, sslSocketFactory, this); + } finally { + unlock(); } - inCache = true; - kac.put(url, sslSocketFactory, this); } /* diff --git a/src/java.base/share/classes/sun/nio/ch/DatagramSocketAdaptor.java b/src/java.base/share/classes/sun/nio/ch/DatagramSocketAdaptor.java index abe33000cda6099baa974a1372fe2f65b2b7ebde..d962cdf36930a62f53207fbd5c60512f769cf0f9 100644 --- a/src/java.base/share/classes/sun/nio/ch/DatagramSocketAdaptor.java +++ b/src/java.base/share/classes/sun/nio/ch/DatagramSocketAdaptor.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 @@ -219,9 +219,7 @@ public class DatagramSocketAdaptor } catch (AlreadyConnectedException e) { throw new IllegalArgumentException("Connected and packet address differ"); } catch (ClosedChannelException e) { - var exc = new SocketException("Socket closed"); - exc.initCause(e); - throw exc; + throw new SocketException("Socket closed", e); } } finally { if (bb != null) { @@ -249,9 +247,7 @@ public class DatagramSocketAdaptor p.setSocketAddress(sender); } } catch (ClosedChannelException e) { - var exc = new SocketException("Socket closed"); - exc.initCause(e); - throw exc; + throw new SocketException("Socket closed", e); } finally { Util.offerFirstTemporaryDirectBuffer(bb); } @@ -481,7 +477,7 @@ public class DatagramSocketAdaptor joinGroup(new InetSocketAddress(group, 0), null); } catch (IllegalArgumentException iae) { // 1-arg joinGroup does not specify IllegalArgumentException - throw (SocketException) new SocketException("joinGroup failed").initCause(iae); + throw new SocketException("joinGroup failed", iae); } } @@ -493,7 +489,7 @@ public class DatagramSocketAdaptor leaveGroup(new InetSocketAddress(group, 0), null); } catch (IllegalArgumentException iae) { // 1-arg leaveGroup does not specify IllegalArgumentException - throw (SocketException) new SocketException("leaveGroup failed").initCause(iae); + throw new SocketException("leaveGroup failed", iae); } } diff --git a/src/java.base/share/classes/sun/nio/ch/FileChannelImpl.java b/src/java.base/share/classes/sun/nio/ch/FileChannelImpl.java index ec0bc767eb7a4c1a791da8144afece6bdfd8a9dc..31a54a57a75ec56733fabed59a0be310766bca26 100644 --- a/src/java.base/share/classes/sun/nio/ch/FileChannelImpl.java +++ b/src/java.base/share/classes/sun/nio/ch/FileChannelImpl.java @@ -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 @@ -1271,6 +1271,8 @@ public class FileChannelImpl throw new NonReadableChannelException(); if (!shared && !writable) throw new NonWritableChannelException(); + if (size == 0) + size = Long.MAX_VALUE - Math.max(0, position); FileLockImpl fli = new FileLockImpl(this, position, size, shared); FileLockTable flt = fileLockTable(); flt.add(fli); @@ -1316,6 +1318,8 @@ public class FileChannelImpl throw new NonReadableChannelException(); if (!shared && !writable) throw new NonWritableChannelException(); + if (size == 0) + size = Long.MAX_VALUE - Math.max(0, position); FileLockImpl fli = new FileLockImpl(this, position, size, shared); FileLockTable flt = fileLockTable(); flt.add(fli); diff --git a/src/java.base/share/classes/sun/nio/ch/SimpleAsynchronousFileChannelImpl.java b/src/java.base/share/classes/sun/nio/ch/SimpleAsynchronousFileChannelImpl.java index 5658480558f77a2eace70f9143add8730b28121f..b41430c8d9d6975729ebd13471b8b12925e141d0 100644 --- a/src/java.base/share/classes/sun/nio/ch/SimpleAsynchronousFileChannelImpl.java +++ b/src/java.base/share/classes/sun/nio/ch/SimpleAsynchronousFileChannelImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2013, 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 @@ -181,8 +181,10 @@ public class SimpleAsynchronousFileChannelImpl if (!shared && !writing) throw new NonWritableChannelException(); + long len = (size != 0) ? size : Long.MAX_VALUE - Math.max(0, position); + // add to lock table - final FileLockImpl fli = addToFileLockTable(position, size, shared); + final FileLockImpl fli = addToFileLockTable(position, len, shared); if (fli == null) { Throwable exc = new ClosedChannelException(); if (handler == null) @@ -203,7 +205,7 @@ public class SimpleAsynchronousFileChannelImpl try { begin(); do { - n = nd.lock(fdObj, true, position, size, shared); + n = nd.lock(fdObj, true, position, len, shared); } while ((n == FileDispatcher.INTERRUPTED) && isOpen()); if (n != FileDispatcher.LOCKED || !isOpen()) { throw new AsynchronousCloseException(); @@ -248,6 +250,9 @@ public class SimpleAsynchronousFileChannelImpl if (!shared && !writing) throw new NonWritableChannelException(); + if (size == 0) + size = Long.MAX_VALUE - Math.max(0, position); + // add to lock table FileLockImpl fli = addToFileLockTable(position, size, shared); if (fli == null) diff --git a/src/java.base/share/classes/sun/security/pkcs/PKCS7.java b/src/java.base/share/classes/sun/security/pkcs/PKCS7.java index 63d1451148f1b1bf3f6aed476488e2d74ff0e955..3484bd04c32d3bfc4bde87ff94c7e3326f8bbb3e 100644 --- a/src/java.base/share/classes/sun/security/pkcs/PKCS7.java +++ b/src/java.base/share/classes/sun/security/pkcs/PKCS7.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2022, Oracle and/or its affiliates. All rights reserved. * 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,6 @@ import sun.security.x509.*; */ public class PKCS7 { - private ObjectIdentifier contentType; - // the ASN.1 members for a signedData (and other) contentTypes private BigInteger version = null; private AlgorithmId[] digestAlgorithmIds = null; @@ -167,7 +165,7 @@ public class PKCS7 { throws IOException { ContentInfo block = new ContentInfo(derin, oldStyle); - contentType = block.contentType; + ObjectIdentifier contentType = block.contentType; DerValue content = block.getContent(); if (contentType.equals(ContentInfo.SIGNED_DATA_OID)) { @@ -240,14 +238,10 @@ public class PKCS7 { bais.close(); bais = null; } - } catch (CertificateException ce) { + } catch (CertificateException | IOException ce) { ParsingException pe = new ParsingException(ce.getMessage()); pe.initCause(ce); throw pe; - } catch (IOException ioe) { - ParsingException pe = new ParsingException(ioe.getMessage()); - pe.initCause(ioe); - throw pe; } finally { if (bais != null) bais.close(); @@ -330,14 +324,10 @@ public class PKCS7 { } count++; } - } catch (CertificateException ce) { + } catch (CertificateException | IOException ce) { ParsingException pe = new ParsingException(ce.getMessage()); pe.initCause(ce); throw pe; - } catch (IOException ioe) { - ParsingException pe = new ParsingException(ioe.getMessage()); - pe.initCause(ioe); - throw pe; } finally { if (bais != null) bais.close(); @@ -444,14 +434,10 @@ public class PKCS7 { bais.close(); bais = null; } - } catch (CertificateException ce) { + } catch (CertificateException | IOException ce) { ParsingException pe = new ParsingException(ce.getMessage()); pe.initCause(ce); throw pe; - } catch (IOException ioe) { - ParsingException pe = new ParsingException(ioe.getMessage()); - pe.initCause(ioe); - throw pe; } finally { if (bais != null) bais.close(); diff --git a/src/java.base/share/classes/sun/security/provider/SunEntries.java b/src/java.base/share/classes/sun/security/provider/SunEntries.java index 912cad5971475253f7fbf544b5f5886ddd370cbf..c7fdd230830f7ce329c9f94d0e86054ef2e65b49 100644 --- a/src/java.base/share/classes/sun/security/provider/SunEntries.java +++ b/src/java.base/share/classes/sun/security/provider/SunEntries.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -210,8 +210,10 @@ public final class SunEntries { /* * Digest engines */ - add(p, "MessageDigest", "MD2", "sun.security.provider.MD2", attrs); - add(p, "MessageDigest", "MD5", "sun.security.provider.MD5", attrs); + addWithAlias(p, "MessageDigest", "MD2", "sun.security.provider.MD2", + attrs); + addWithAlias(p, "MessageDigest", "MD5", "sun.security.provider.MD5", + attrs); addWithAlias(p, "MessageDigest", "SHA-1", "sun.security.provider.SHA", attrs); diff --git a/src/java.base/share/classes/sun/security/ssl/Alert.java b/src/java.base/share/classes/sun/security/ssl/Alert.java index bc034dc8c3bcfbc0eae58c61e75d7017a5b4e3eb..922937887aaaceb25a202578dda1eecc191e6fc9 100644 --- a/src/java.base/share/classes/sun/security/ssl/Alert.java +++ b/src/java.base/share/classes/sun/security/ssl/Alert.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 @@ -122,22 +122,15 @@ enum Alert { reason = (cause != null) ? cause.getMessage() : ""; } - SSLException ssle; if (cause instanceof IOException) { - ssle = new SSLException(reason); + return new SSLException(reason, cause); } else if ((this == UNEXPECTED_MESSAGE)) { - ssle = new SSLProtocolException(reason); + return new SSLProtocolException(reason, cause); } else if (handshakeOnly) { - ssle = new SSLHandshakeException(reason); + return new SSLHandshakeException(reason, cause); } else { - ssle = new SSLException(reason); + return new SSLException(reason, cause); } - - if (cause != null) { - ssle.initCause(cause); - } - - return ssle; } /** diff --git a/src/java.base/share/classes/sun/security/ssl/CipherSuite.java b/src/java.base/share/classes/sun/security/ssl/CipherSuite.java index 8500ae7e188ee0c750a01f647eaf6b6ae8fd22dd..d957d7b20bdda7ee183a916f0fd2d01c687bbd6a 100644 --- a/src/java.base/share/classes/sun/security/ssl/CipherSuite.java +++ b/src/java.base/share/classes/sun/security/ssl/CipherSuite.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 @@ -54,9 +54,9 @@ enum CipherSuite { // changed later, see below). // 2. Prefer forward secrecy cipher suites. // 3. Prefer the stronger bulk cipher, in the order of AES_256(GCM), - // AES_128(GCM), AES_256, AES_128, 3DES-EDE. + // AES_128(GCM), AES_256, AES_128. // 4. Prefer the stronger MAC algorithm, in the order of SHA384, - // SHA256, SHA, MD5. + // SHA256, SHA. // 5. Prefer the better performance of key exchange and digital // signature algorithm, in the order of ECDHE-ECDSA, ECDHE-RSA, // DHE-RSA, DHE-DSS, ECDH-ECDSA, ECDH-RSA, RSA. @@ -327,41 +327,6 @@ enum CipherSuite { ProtocolVersion.PROTOCOLS_TO_12, K_RSA, B_AES_128, M_SHA, H_SHA256), - // 3DES_EDE, forward secrecy. - TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA( - 0xC008, true, "TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA", "", - ProtocolVersion.PROTOCOLS_TO_12, - K_ECDHE_ECDSA, B_3DES, M_SHA, H_SHA256), - TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA( - 0xC012, true, "TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA", "", - ProtocolVersion.PROTOCOLS_TO_12, - K_ECDHE_RSA, B_3DES, M_SHA, H_SHA256), - SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA( - 0x0016, true, "SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA", - "TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA", - ProtocolVersion.PROTOCOLS_TO_12, - K_DHE_RSA, B_3DES, M_SHA, H_SHA256), - SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA( - 0x0013, true, "SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA", - "TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA", - ProtocolVersion.PROTOCOLS_TO_12, - K_DHE_DSS, B_3DES, M_SHA, H_SHA256), - - // 3DES_EDE, not forward secrecy. - TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA( - 0xC003, true, "TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA", "", - ProtocolVersion.PROTOCOLS_TO_12, - K_ECDH_ECDSA, B_3DES, M_SHA, H_SHA256), - TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA( - 0xC00D, true, "TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA", "", - ProtocolVersion.PROTOCOLS_TO_12, - K_ECDH_RSA, B_3DES, M_SHA, H_SHA256), - SSL_RSA_WITH_3DES_EDE_CBC_SHA( - 0x000A, true, "SSL_RSA_WITH_3DES_EDE_CBC_SHA", - "TLS_RSA_WITH_3DES_EDE_CBC_SHA", - ProtocolVersion.PROTOCOLS_TO_12, - K_RSA, B_3DES, M_SHA, H_SHA256), - // Renegotiation protection request Signalling Cipher Suite Value (SCSV). TLS_EMPTY_RENEGOTIATION_INFO_SCSV( // RFC 5746, TLS 1.2 and prior 0x00FF, true, "TLS_EMPTY_RENEGOTIATION_INFO_SCSV", "", @@ -413,6 +378,41 @@ enum CipherSuite { 0x0034, false, "TLS_DH_anon_WITH_AES_128_CBC_SHA", "", ProtocolVersion.PROTOCOLS_TO_12, K_DH_ANON, B_AES_128, M_SHA, H_SHA256), + + // 3DES_EDE, forward secrecy. + TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA( + 0xC008, false, "TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA", "", + ProtocolVersion.PROTOCOLS_TO_12, + K_ECDHE_ECDSA, B_3DES, M_SHA, H_SHA256), + TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA( + 0xC012, false, "TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA", "", + ProtocolVersion.PROTOCOLS_TO_12, + K_ECDHE_RSA, B_3DES, M_SHA, H_SHA256), + SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA( + 0x0016, false, "SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA", + "TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA", + ProtocolVersion.PROTOCOLS_TO_12, + K_DHE_RSA, B_3DES, M_SHA, H_SHA256), + SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA( + 0x0013, false, "SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA", + "TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA", + ProtocolVersion.PROTOCOLS_TO_12, + K_DHE_DSS, B_3DES, M_SHA, H_SHA256), + + // 3DES_EDE, not forward secrecy. + TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA( + 0xC003, false, "TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA", "", + ProtocolVersion.PROTOCOLS_TO_12, + K_ECDH_ECDSA, B_3DES, M_SHA, H_SHA256), + TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA( + 0xC00D, false, "TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA", "", + ProtocolVersion.PROTOCOLS_TO_12, + K_ECDH_RSA, B_3DES, M_SHA, H_SHA256), + SSL_RSA_WITH_3DES_EDE_CBC_SHA( + 0x000A, false, "SSL_RSA_WITH_3DES_EDE_CBC_SHA", + "TLS_RSA_WITH_3DES_EDE_CBC_SHA", + ProtocolVersion.PROTOCOLS_TO_12, + K_RSA, B_3DES, M_SHA, H_SHA256), TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA( 0xC017, false, "TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA", "", ProtocolVersion.PROTOCOLS_TO_12, diff --git a/src/java.base/share/classes/sun/security/ssl/DHClientKeyExchange.java b/src/java.base/share/classes/sun/security/ssl/DHClientKeyExchange.java index f9753ffe078b6c13f813e23500aa9556c75e27b0..996e3f78ec162b97f95b3abbe150f7a8d942f120 100644 --- a/src/java.base/share/classes/sun/security/ssl/DHClientKeyExchange.java +++ b/src/java.base/share/classes/sun/security/ssl/DHClientKeyExchange.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 @@ -295,8 +295,8 @@ final class DHClientKeyExchange { shc.handshakeCredentials.add( new DHECredentials(peerPublicKey, namedGroup)); } catch (GeneralSecurityException | java.io.IOException e) { - throw (SSLHandshakeException)(new SSLHandshakeException( - "Could not generate DHPublicKey").initCause(e)); + throw new SSLHandshakeException( + "Could not generate DHPublicKey", e); } // update the states diff --git a/src/java.base/share/classes/sun/security/ssl/ECDHKeyExchange.java b/src/java.base/share/classes/sun/security/ssl/ECDHKeyExchange.java index 59bc40411ce86580ebfefd2a6daf62d985aa4cc9..9833ea94e8d48ec3aa80f87226fbf16515c275da 100644 --- a/src/java.base/share/classes/sun/security/ssl/ECDHKeyExchange.java +++ b/src/java.base/share/classes/sun/security/ssl/ECDHKeyExchange.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 @@ -160,8 +160,7 @@ final class ECDHKeyExchange { ka.doPhase(peerPublicKey, true); return ka.generateSecret("TlsPremasterSecret"); } catch (GeneralSecurityException e) { - throw (SSLHandshakeException) new SSLHandshakeException( - "Could not generate secret").initCause(e); + throw new SSLHandshakeException("Could not generate secret", e); } } @@ -177,8 +176,7 @@ final class ECDHKeyExchange { PublicKey peerPublicKey = kf.generatePublic(spec); return getAgreedSecret(peerPublicKey); } catch (GeneralSecurityException | java.io.IOException e) { - throw (SSLHandshakeException) new SSLHandshakeException( - "Could not generate secret").initCause(e); + throw new SSLHandshakeException("Could not generate secret", e); } } @@ -202,8 +200,8 @@ final class ECDHKeyExchange { "ECPublicKey does not comply to algorithm constraints"); } } catch (GeneralSecurityException | java.io.IOException e) { - throw (SSLHandshakeException) new SSLHandshakeException( - "Could not generate ECPublicKey").initCause(e); + throw new SSLHandshakeException( + "Could not generate ECPublicKey", e); } } diff --git a/src/java.base/share/classes/sun/security/ssl/KAKeyDerivation.java b/src/java.base/share/classes/sun/security/ssl/KAKeyDerivation.java index 7c791e85f773481a632d3313fc62bde60637c353..b76da75c763cca16cb8933af724c3ac86a371e6c 100644 --- a/src/java.base/share/classes/sun/security/ssl/KAKeyDerivation.java +++ b/src/java.base/share/classes/sun/security/ssl/KAKeyDerivation.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 @@ -88,8 +88,7 @@ public class KAKeyDerivation implements SSLKeyDerivation { context, preMasterSecret); return kd.deriveKey("MasterSecret", params); } catch (GeneralSecurityException gse) { - throw (SSLHandshakeException) new SSLHandshakeException( - "Could not generate secret").initCause(gse); + throw new SSLHandshakeException("Could not generate secret", gse); } } @@ -125,8 +124,7 @@ public class KAKeyDerivation implements SSLKeyDerivation { // derive handshake secret return hkdf.extract(saltSecret, sharedSecret, algorithm); } catch (GeneralSecurityException gse) { - throw (SSLHandshakeException) new SSLHandshakeException( - "Could not generate secret").initCause(gse); + throw new SSLHandshakeException("Could not generate secret", gse); } } } diff --git a/src/java.base/share/classes/sun/security/ssl/NewSessionTicket.java b/src/java.base/share/classes/sun/security/ssl/NewSessionTicket.java index 50f19dbf715c1e101a92923f098b54edb0b68eff..337c83849915be30a3e27e862ef571cc3dc0406b 100644 --- a/src/java.base/share/classes/sun/security/ssl/NewSessionTicket.java +++ b/src/java.base/share/classes/sun/security/ssl/NewSessionTicket.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 @@ -302,8 +302,7 @@ final class NewSessionTicket { return hkdf.expand(resumptionMasterSecret, hkdfInfo, hashAlg.hashLength, "TlsPreSharedKey"); } catch (GeneralSecurityException gse) { - throw (SSLHandshakeException) new SSLHandshakeException( - "Could not derive PSK").initCause(gse); + throw new SSLHandshakeException("Could not derive PSK", gse); } } diff --git a/src/java.base/share/classes/sun/security/ssl/ProtocolVersion.java b/src/java.base/share/classes/sun/security/ssl/ProtocolVersion.java index e4cb5637c60e1cf55cce2c10a71e069bc435ce2f..32c112a499126476b1f100b1e2f993c7316abb75 100644 --- a/src/java.base/share/classes/sun/security/ssl/ProtocolVersion.java +++ b/src/java.base/share/classes/sun/security/ssl/ProtocolVersion.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 @@ -290,7 +290,7 @@ enum ProtocolVersion { ProtocolVersion pv = ProtocolVersion.nameOf(pn); if (pv == null) { throw new IllegalArgumentException( - "Unsupported protocol" + pn); + "Unsupported protocol: " + pn); } pvs.add(pv); diff --git a/src/java.base/share/classes/sun/security/ssl/SSLBasicKeyDerivation.java b/src/java.base/share/classes/sun/security/ssl/SSLBasicKeyDerivation.java index 7f6934006379551ad9c1fc220f71e67d78c284be..20fc711259379d262fcf866c30d425a23487b6bc 100644 --- a/src/java.base/share/classes/sun/security/ssl/SSLBasicKeyDerivation.java +++ b/src/java.base/share/classes/sun/security/ssl/SSLBasicKeyDerivation.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 @@ -52,8 +52,7 @@ final class SSLBasicKeyDerivation implements SSLKeyDerivation { return hkdf.expand(secret, hkdfInfo, ((SecretSizeSpec)keySpec).length, algorithm); } catch (GeneralSecurityException gse) { - throw (SSLHandshakeException) new SSLHandshakeException( - "Could not generate secret").initCause(gse); + throw new SSLHandshakeException("Could not generate secret", gse); } } diff --git a/src/java.base/share/classes/sun/security/ssl/SSLCipher.java b/src/java.base/share/classes/sun/security/ssl/SSLCipher.java index 26e7ea2225d749fe11e5533b91c3d0398a3878d2..d44fb11014e1f202ef90342af66612065f16d71d 100644 --- a/src/java.base/share/classes/sun/security/ssl/SSLCipher.java +++ b/src/java.base/share/classes/sun/security/ssl/SSLCipher.java @@ -39,6 +39,7 @@ import java.security.spec.AlgorithmParameterSpec; import java.util.AbstractMap.SimpleImmutableEntry; import java.util.Arrays; import java.util.HashMap; +import java.util.Locale; import java.util.Map; import javax.crypto.BadPaddingException; import javax.crypto.Cipher; @@ -430,7 +431,8 @@ enum SSLCipher { for (String entry : propvalue) { int index; // If this is not a UsageLimit, goto to next entry. - String[] values = entry.trim().toUpperCase().split(" "); + String[] values = + entry.trim().toUpperCase(Locale.ENGLISH).split(" "); if (values[1].contains(tag[0])) { index = 0; @@ -1865,10 +1867,10 @@ enum SSLCipher { this.random = random; keyLimitCountdown = cipherLimits.getOrDefault( - algorithm.toUpperCase() + ":" + tag[0], 0L); + algorithm.toUpperCase(Locale.ENGLISH) + ":" + tag[0], 0L); if (SSLLogger.isOn && SSLLogger.isOn("ssl")) { SSLLogger.fine("KeyLimit read side: algorithm = " + - algorithm.toUpperCase() + ":" + tag[0] + + algorithm + ":" + tag[0] + "\ncountdown value = " + keyLimitCountdown); } if (keyLimitCountdown > 0) { @@ -2019,10 +2021,10 @@ enum SSLCipher { this.random = random; keyLimitCountdown = cipherLimits.getOrDefault( - algorithm.toUpperCase() + ":" + tag[0], 0L); + algorithm.toUpperCase(Locale.ENGLISH) + ":" + tag[0], 0L); if (SSLLogger.isOn && SSLLogger.isOn("ssl")) { SSLLogger.fine("KeyLimit write side: algorithm = " - + algorithm.toUpperCase() + ":" + tag[0] + + + algorithm + ":" + tag[0] + "\ncountdown value = " + keyLimitCountdown); } if (keyLimitCountdown > 0) { @@ -2279,9 +2281,9 @@ enum SSLCipher { this.random = random; keyLimitCountdown = cipherLimits.getOrDefault( - algorithm.toUpperCase() + ":" + tag[0], 0L); + algorithm.toUpperCase(Locale.ENGLISH) + ":" + tag[0], 0L); if (SSLLogger.isOn && SSLLogger.isOn("ssl")) { - SSLLogger.fine("algorithm = " + algorithm.toUpperCase() + + SSLLogger.fine("algorithm = " + algorithm + ":" + tag[0] + "\ncountdown value = " + keyLimitCountdown); } @@ -2561,9 +2563,9 @@ enum SSLCipher { this.random = random; keyLimitCountdown = cipherLimits.getOrDefault( - algorithm.toUpperCase() + ":" + tag[0], 0L); + algorithm.toUpperCase(Locale.ENGLISH) + ":" + tag[0], 0L); if (SSLLogger.isOn && SSLLogger.isOn("ssl")) { - SSLLogger.fine("algorithm = " + algorithm.toUpperCase() + + SSLLogger.fine("algorithm = " + algorithm + ":" + tag[0] + "\ncountdown value = " + keyLimitCountdown); } diff --git a/src/java.base/share/classes/sun/security/ssl/SSLConfiguration.java b/src/java.base/share/classes/sun/security/ssl/SSLConfiguration.java index d267c2e6b467cd30109262928cceff5146c03ab9..056f00a5a3c369ba0a5311d72d7923c5c2d0692d 100644 --- a/src/java.base/share/classes/sun/security/ssl/SSLConfiguration.java +++ b/src/java.base/share/classes/sun/security/ssl/SSLConfiguration.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 @@ -29,11 +29,7 @@ import java.security.AccessControlContext; import java.security.AccessController; import java.security.AlgorithmConstraints; import java.security.NoSuchAlgorithmException; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; +import java.util.*; import java.util.function.BiFunction; import javax.crypto.KeyGenerator; import javax.net.ssl.HandshakeCompletedListener; @@ -66,7 +62,7 @@ final class SSLConfiguration implements Cloneable { // The configured signature schemes for "signature_algorithms" and // "signature_algorithms_cert" extensions - List signatureSchemes; + String[] signatureSchemes; // the maximum protocol version of enabled protocols ProtocolVersion maximumProtocolVersion; @@ -204,6 +200,7 @@ final class SSLConfiguration implements Cloneable { params.setUseCipherSuitesOrder(this.preferLocalCipherSuites); params.setEnableRetransmissions(this.enableRetransmissions); params.setMaximumPacketSize(this.maximumPacketSize); + params.setSignatureSchemes(this.signatureSchemes); return params; } @@ -261,6 +258,13 @@ final class SSLConfiguration implements Cloneable { this.applicationProtocols = sa; } // otherwise, use the default values + String[] ss = params.getSignatureSchemes(); + if (ss != null) { + // Note if 'ss' is empty, then no signature schemes should be + // specified over the connections. + this.signatureSchemes = ss; + } // Otherwise, use the default values + this.preferLocalCipherSuites = params.getUseCipherSuitesOrder(); this.enableRetransmissions = params.getEnableRetransmissions(); this.maximumPacketSize = params.getMaximumPacketSize(); @@ -403,10 +407,15 @@ final class SSLConfiguration implements Cloneable { void toggleClientMode() { this.isClientMode ^= true; - // reset the signature schemes - this.signatureSchemes = isClientMode ? - CustomizedClientSignatureSchemes.signatureSchemes : - CustomizedServerSignatureSchemes.signatureSchemes; + // Reset the signature schemes, if it was configured with SSLParameters. + if (Arrays.equals(signatureSchemes, + CustomizedClientSignatureSchemes.signatureSchemes) || + Arrays.equals(signatureSchemes, + CustomizedServerSignatureSchemes.signatureSchemes)) { + this.signatureSchemes = isClientMode ? + CustomizedClientSignatureSchemes.signatureSchemes : + CustomizedServerSignatureSchemes.signatureSchemes; + } } @Override @@ -434,7 +443,7 @@ final class SSLConfiguration implements Cloneable { // // See Effective Java Second Edition: Item 71. private static final class CustomizedClientSignatureSchemes { - private static final List signatureSchemes = + private static final String[] signatureSchemes = getCustomizedSignatureScheme("jdk.tls.client.SignatureSchemes"); } @@ -442,7 +451,7 @@ final class SSLConfiguration implements Cloneable { // // See Effective Java Second Edition: Item 71. private static final class CustomizedServerSignatureSchemes { - private static final List signatureSchemes = + private static final String[] signatureSchemes = getCustomizedSignatureScheme("jdk.tls.server.SignatureSchemes"); } @@ -450,14 +459,12 @@ final class SSLConfiguration implements Cloneable { * Get the customized signature schemes specified by the given * system property. */ - private static List getCustomizedSignatureScheme( - String propertyName) { - + private static String[] getCustomizedSignatureScheme(String propertyName) { String property = GetPropertyAction.privilegedGetProperty(propertyName); if (SSLLogger.isOn && SSLLogger.isOn("ssl,sslctx")) { SSLLogger.fine( "System property " + propertyName + " is set to '" + - property + "'"); + property + "'"); } if (property != null && !property.isEmpty()) { // remove double quote marks from beginning/end of the property @@ -469,31 +476,34 @@ final class SSLConfiguration implements Cloneable { if (property != null && !property.isEmpty()) { String[] signatureSchemeNames = property.split(","); - List signatureSchemes = - new ArrayList<>(signatureSchemeNames.length); - for (int i = 0; i < signatureSchemeNames.length; i++) { - signatureSchemeNames[i] = signatureSchemeNames[i].trim(); - if (signatureSchemeNames[i].isEmpty()) { + List signatureSchemes = + new ArrayList<>(signatureSchemeNames.length); + for (String schemeName : signatureSchemeNames) { + schemeName = schemeName.trim(); + if (schemeName.isEmpty()) { continue; } - SignatureScheme scheme = - SignatureScheme.nameOf(signatureSchemeNames[i]); + // Check the availability + SignatureScheme scheme = SignatureScheme.nameOf(schemeName); if (scheme != null && scheme.isAvailable) { - signatureSchemes.add(scheme); + signatureSchemes.add(schemeName); } else { if (SSLLogger.isOn && SSLLogger.isOn("ssl,sslctx")) { SSLLogger.fine( - "The current installed providers do not " + - "support signature scheme: " + - signatureSchemeNames[i]); + "The current installed providers do not " + + "support signature scheme: " + schemeName); } } } - return signatureSchemes; + if (!signatureSchemes.isEmpty()) { + return signatureSchemes.toArray(new String[0]); + } } - return Collections.emptyList(); + // Note that if the System Property value is not defined (JDK + // default value) or empty, the provider-specific default is used. + return null; } } diff --git a/src/java.base/share/classes/sun/security/ssl/SSLEngineImpl.java b/src/java.base/share/classes/sun/security/ssl/SSLEngineImpl.java index ca4a80c5a5c550706ab85692df6c7e5170f3a62e..1db9ba8d86bad0a3db0a96b80a8b59f48f425dba 100644 --- a/src/java.base/share/classes/sun/security/ssl/SSLEngineImpl.java +++ b/src/java.base/share/classes/sun/security/ssl/SSLEngineImpl.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 @@ -1167,17 +1167,13 @@ final class SSLEngineImpl extends SSLEngine implements SSLTransport { if (taskThrown instanceof RuntimeException) { throw new RuntimeException(msg, taskThrown); } else if (taskThrown instanceof SSLHandshakeException) { - return (SSLHandshakeException) - new SSLHandshakeException(msg).initCause(taskThrown); + return new SSLHandshakeException(msg, taskThrown); } else if (taskThrown instanceof SSLKeyException) { - return (SSLKeyException) - new SSLKeyException(msg).initCause(taskThrown); + return new SSLKeyException(msg, taskThrown); } else if (taskThrown instanceof SSLPeerUnverifiedException) { - return (SSLPeerUnverifiedException) - new SSLPeerUnverifiedException(msg).initCause(taskThrown); + return new SSLPeerUnverifiedException(msg, taskThrown); } else if (taskThrown instanceof SSLProtocolException) { - return (SSLProtocolException) - new SSLProtocolException(msg).initCause(taskThrown); + return new SSLProtocolException(msg, taskThrown); } else if (taskThrown instanceof SSLException) { return (SSLException)taskThrown; } else { diff --git a/src/java.base/share/classes/sun/security/ssl/SSLEngineInputRecord.java b/src/java.base/share/classes/sun/security/ssl/SSLEngineInputRecord.java index 938768aaf76bb26fd53b9342e9c5f5497b87bcb4..dc957ca141949a99d2c155cd445895091724f4cb 100644 --- a/src/java.base/share/classes/sun/security/ssl/SSLEngineInputRecord.java +++ b/src/java.base/share/classes/sun/security/ssl/SSLEngineInputRecord.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -242,8 +242,7 @@ final class SSLEngineInputRecord extends InputRecord implements SSLRecord { } catch (BadPaddingException bpe) { throw bpe; } catch (GeneralSecurityException gse) { - throw (SSLProtocolException)(new SSLProtocolException( - "Unexpected exception")).initCause(gse); + throw new SSLProtocolException("Unexpected exception", gse); } finally { // consume a complete record packet.limit(srcLim); diff --git a/src/java.base/share/classes/sun/security/ssl/SSLSecretDerivation.java b/src/java.base/share/classes/sun/security/ssl/SSLSecretDerivation.java index a7ba9a5e566a5aeabfae7e0083d63ec4d42e4807..ff13948a67c20b65b4b5c2e48112ff17b3fd2b6e 100644 --- a/src/java.base/share/classes/sun/security/ssl/SSLSecretDerivation.java +++ b/src/java.base/share/classes/sun/security/ssl/SSLSecretDerivation.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 @@ -113,8 +113,7 @@ final class SSLSecretDerivation implements SSLKeyDerivation { HKDF hkdf = new HKDF(hashAlg.name); return hkdf.expand(secret, hkdfInfo, hashAlg.hashLength, algorithm); } catch (GeneralSecurityException gse) { - throw (SSLHandshakeException) new SSLHandshakeException( - "Could not generate secret").initCause(gse); + throw new SSLHandshakeException("Could not generate secret", gse); } } diff --git a/src/java.base/share/classes/sun/security/ssl/SSLSocketImpl.java b/src/java.base/share/classes/sun/security/ssl/SSLSocketImpl.java index 842cef119113d02abe9fa9c6196b5dc8942cf633..68fb386020339c39e6d9d608223714659b59552a 100644 --- a/src/java.base/share/classes/sun/security/ssl/SSLSocketImpl.java +++ b/src/java.base/share/classes/sun/security/ssl/SSLSocketImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -1709,19 +1709,13 @@ public final class SSLSocketImpl private Plaintext handleEOF(EOFException eofe) throws IOException { if (requireCloseNotify || conContext.handshakeContext != null) { - SSLException ssle; if (conContext.handshakeContext != null) { - ssle = new SSLHandshakeException( - "Remote host terminated the handshake"); + throw new SSLHandshakeException( + "Remote host terminated the handshake", eofe); } else { - ssle = new SSLProtocolException( - "Remote host terminated the connection"); - } - - if (eofe != null) { - ssle.initCause(eofe); + throw new SSLProtocolException( + "Remote host terminated the connection", eofe); } - throw ssle; } else { // treat as if we had received a close_notify conContext.isInputCloseNotified = true; diff --git a/src/java.base/share/classes/sun/security/ssl/SSLSocketInputRecord.java b/src/java.base/share/classes/sun/security/ssl/SSLSocketInputRecord.java index da189f4f3fff342abd2e53a47f642d25c22507b7..7afacb0f3d77c96e7d233428a54d1b0f086e1a93 100644 --- a/src/java.base/share/classes/sun/security/ssl/SSLSocketInputRecord.java +++ b/src/java.base/share/classes/sun/security/ssl/SSLSocketInputRecord.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2022, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2020, Azul Systems, Inc. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -263,8 +263,7 @@ final class SSLSocketInputRecord extends InputRecord implements SSLRecord { } catch (BadPaddingException bpe) { throw bpe; } catch (GeneralSecurityException gse) { - throw (SSLProtocolException)(new SSLProtocolException( - "Unexpected exception")).initCause(gse); + throw new SSLProtocolException("Unexpected exception", gse); } if (contentType != ContentType.HANDSHAKE.id && diff --git a/src/java.base/share/classes/sun/security/ssl/SSLTrafficKeyDerivation.java b/src/java.base/share/classes/sun/security/ssl/SSLTrafficKeyDerivation.java index ac39cbb16fbd930d0befc33522127fbd2f6dc11e..6e890c8818dc05228f50052cc5284fb707283b7b 100644 --- a/src/java.base/share/classes/sun/security/ssl/SSLTrafficKeyDerivation.java +++ b/src/java.base/share/classes/sun/security/ssl/SSLTrafficKeyDerivation.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 @@ -154,8 +154,8 @@ enum SSLTrafficKeyDerivation implements SSLKeyDerivationGenerator { ks.getKeyLength(cs), ks.getAlgorithm(cs, algorithm)); } catch (GeneralSecurityException gse) { - throw (SSLHandshakeException)(new SSLHandshakeException( - "Could not generate secret").initCause(gse)); + throw new SSLHandshakeException( + "Could not generate secret", gse); } } diff --git a/src/java.base/share/classes/sun/security/ssl/ServerHello.java b/src/java.base/share/classes/sun/security/ssl/ServerHello.java index 193a71cde861ebaac056b74caa2650051ce33a39..efbe860bfd6be6fc64dfe73a31c19e95039ad6c2 100644 --- a/src/java.base/share/classes/sun/security/ssl/ServerHello.java +++ b/src/java.base/share/classes/sun/security/ssl/ServerHello.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2020, 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 @@ -1205,8 +1205,7 @@ final class ServerHello { hc.handshakeKeyDerivation = new SSLSecretDerivation(hc, earlySecret); } catch (GeneralSecurityException gse) { - throw (SSLHandshakeException) new SSLHandshakeException( - "Could not generate secret").initCause(gse); + throw new SSLHandshakeException("Could not generate secret", gse); } } diff --git a/src/java.base/share/classes/sun/security/ssl/ServerNameExtension.java b/src/java.base/share/classes/sun/security/ssl/ServerNameExtension.java index 74f38bf5b56c448f84d0ca3bef6143c8e17b6404..eaf154af3bb4c989df54cc609d7d14f0f570039e 100644 --- a/src/java.base/share/classes/sun/security/ssl/ServerNameExtension.java +++ b/src/java.base/share/classes/sun/security/ssl/ServerNameExtension.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 @@ -135,9 +135,8 @@ final class ServerNameExtension { nameType + "), name=" + (new String(encoded, StandardCharsets.UTF_8)) + ", value={" + - Utilities.toHexString(encoded) + "}"); - throw hc.conContext.fatal(Alert.ILLEGAL_PARAMETER, - (SSLProtocolException)spe.initCause(iae)); + Utilities.toHexString(encoded) + "}", iae); + throw hc.conContext.fatal(Alert.ILLEGAL_PARAMETER, spe); } } else { try { @@ -146,9 +145,8 @@ final class ServerNameExtension { SSLProtocolException spe = new SSLProtocolException( "Illegal server name, type=(" + nameType + "), value={" + - Utilities.toHexString(encoded) + "}"); - throw hc.conContext.fatal(Alert.ILLEGAL_PARAMETER, - (SSLProtocolException)spe.initCause(iae)); + Utilities.toHexString(encoded) + "}", iae); + throw hc.conContext.fatal(Alert.ILLEGAL_PARAMETER, spe); } } diff --git a/src/java.base/share/classes/sun/security/ssl/SignatureScheme.java b/src/java.base/share/classes/sun/security/ssl/SignatureScheme.java index 706cb4371d3da0888efe089f11e9edd4f7923202..87feda0e83bee8a3b85eec0d1a8c829ef9168988 100644 --- a/src/java.base/share/classes/sun/security/ssl/SignatureScheme.java +++ b/src/java.base/share/classes/sun/security/ssl/SignatureScheme.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 @@ -181,7 +181,7 @@ enum SignatureScheme { "anonymous", "rsa", "dsa", "ecdsa", }; - static enum SigAlgParamSpec { // support RSASSA-PSS only now + enum SigAlgParamSpec { // support RSASSA-PSS only now RSA_PSS_SHA256 ("SHA-256", 32), RSA_PSS_SHA384 ("SHA-384", 48), RSA_PSS_SHA512 ("SHA-512", 64); @@ -224,13 +224,13 @@ enum SignatureScheme { Collections.unmodifiableSet(EnumSet.of(CryptoPrimitive.SIGNATURE)); - private SignatureScheme(int id, String name, + SignatureScheme(int id, String name, String algorithm, String keyAlgorithm, ProtocolVersion[] supportedProtocols) { this(id, name, algorithm, keyAlgorithm, -1, supportedProtocols); } - private SignatureScheme(int id, String name, + SignatureScheme(int id, String name, String algorithm, String keyAlgorithm, int minimalKeySize, ProtocolVersion[] supportedProtocols) { @@ -238,7 +238,7 @@ enum SignatureScheme { null, minimalKeySize, supportedProtocols); } - private SignatureScheme(int id, String name, + SignatureScheme(int id, String name, String algorithm, String keyAlgorithm, SigAlgParamSpec signAlgParamSpec, int minimalKeySize, ProtocolVersion[] supportedProtocols) { @@ -247,7 +247,7 @@ enum SignatureScheme { supportedProtocols, supportedProtocols); } - private SignatureScheme(int id, String name, + SignatureScheme(int id, String name, String algorithm, String keyAlgorithm, NamedGroup namedGroup, ProtocolVersion[] supportedProtocols) { @@ -256,7 +256,7 @@ enum SignatureScheme { supportedProtocols, supportedProtocols); } - private SignatureScheme(int id, String name, + SignatureScheme(int id, String name, String algorithm, String keyAlgorithm, SigAlgParamSpec signAlgParams, NamedGroup namedGroup, int minimalKeySize, @@ -376,15 +376,10 @@ enum SignatureScheme { List activeProtocols) { List supported = new LinkedList<>(); - // If config.signatureSchemes is non-empty then it means that - // it was defined by a System property. Per - // SSLConfiguration.getCustomizedSignatureScheme() the list will - // only contain schemes that are in the enum. - // Otherwise, use the enum constants (converted to a List). List schemesToCheck = - config.signatureSchemes.isEmpty() ? + config.signatureSchemes == null ? Arrays.asList(SignatureScheme.values()) : - config.signatureSchemes; + namesOfAvailable(config.signatureSchemes); for (SignatureScheme ss: schemesToCheck) { if (!ss.isAvailable) { @@ -437,8 +432,8 @@ enum SignatureScheme { } } else if (ss.isAvailable && ss.supportedProtocols.contains(protocolVersion) && - (config.signatureSchemes.isEmpty() || - config.signatureSchemes.contains(ss)) && + (config.signatureSchemes == null || + Utilities.contains(config.signatureSchemes, ss.name)) && ss.isPermitted(constraints)) { supported.add(ss); } else { @@ -563,6 +558,33 @@ enum SignatureScheme { return new String[0]; } + private static List namesOfAvailable( + String[] signatureSchemes) { + + if (signatureSchemes == null || signatureSchemes.length == 0) { + return Collections.emptyList(); + } + + List sss = new ArrayList<>(signatureSchemes.length); + for (String ss : signatureSchemes) { + SignatureScheme scheme = SignatureScheme.nameOf(ss); + if (scheme == null || !scheme.isAvailable) { + if (SSLLogger.isOn && + SSLLogger.isOn("ssl,handshake,verbose")) { + SSLLogger.finest( + "Ignore the signature algorithm (" + ss + + "), unsupported or unavailable"); + } + + continue; + } + + sss.add(scheme); + } + + return sss; + } + // This method is used to get the signature instance of this signature // scheme for the specific public key. Unlike getSigner(), the exception // is bubbled up. If the public key does not support this signature diff --git a/src/java.base/share/classes/sun/security/ssl/Utilities.java b/src/java.base/share/classes/sun/security/ssl/Utilities.java index 8317d9ae3cbc1baa4badc931ab37c3e3ef64e8df..441f978c84f23b5e1b079d11b8578a1981a21221 100644 --- a/src/java.base/share/classes/sun/security/ssl/Utilities.java +++ b/src/java.base/share/classes/sun/security/ssl/Utilities.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 @@ -229,6 +229,16 @@ final class Utilities { } } + static boolean contains(T[] array, T item) { + for (T t : array) { + if (item.equals(t)) { + return true; + } + } + + return false; + } + private static void swap(byte[] arr, int i, int j) { byte tmp = arr[i]; arr[i] = arr[j]; diff --git a/src/java.base/share/classes/sun/security/tools/keytool/Main.java b/src/java.base/share/classes/sun/security/tools/keytool/Main.java index ae012d3747a97deab0479effd14c7569c73ba686..462606c7f84c28176c44a0f549b6c410c85f677a 100644 --- a/src/java.base/share/classes/sun/security/tools/keytool/Main.java +++ b/src/java.base/share/classes/sun/security/tools/keytool/Main.java @@ -42,8 +42,6 @@ import java.security.cert.TrustAnchor; import java.security.cert.URICertStoreParameters; -import java.security.interfaces.ECKey; -import java.security.interfaces.EdECKey; import java.security.spec.ECParameterSpec; import java.text.Collator; import java.text.MessageFormat; @@ -1286,6 +1284,7 @@ public final class Main { kssave = true; } else if (command == LIST) { if (storePass == null + && !protectedPath && !KeyStoreUtil.isWindowsKeyStore(storetype) && !isPasswordlessKeyStore) { printNoIntegrityWarning(); @@ -1685,6 +1684,7 @@ public final class Main { throws Exception { if (storePass == null + && !protectedPath && !KeyStoreUtil.isWindowsKeyStore(storetype) && !isPasswordlessKeyStore) { printNoIntegrityWarning(); @@ -2016,7 +2016,7 @@ public final class Main { ("Generating.keysize.bit.keyAlgName.key.pair.and.a.certificate.sigAlgName.issued.by.signerAlias.with.a.validity.of.validality.days.for")); Object[] source = { groupName == null ? keysize : KeyUtil.getKeySize(privKey), - fullDisplayAlgName(privKey), + KeyUtil.fullDisplayAlgName(privKey), newCert.getSigAlgName(), signerAlias, validity, @@ -2027,7 +2027,7 @@ public final class Main { ("Generating.keysize.bit.keyAlgName.key.pair.and.self.signed.certificate.sigAlgName.with.a.validity.of.validality.days.for")); Object[] source = { groupName == null ? keysize : KeyUtil.getKeySize(privKey), - fullDisplayAlgName(privKey), + KeyUtil.fullDisplayAlgName(privKey), newCert.getSigAlgName(), validity, x500Name}; @@ -3558,24 +3558,10 @@ public final class Main { } } - private String fullDisplayAlgName(Key key) { - String result = key.getAlgorithm(); - if (key instanceof ECKey) { - ECParameterSpec paramSpec = ((ECKey) key).getParams(); - if (paramSpec instanceof NamedCurve) { - NamedCurve nc = (NamedCurve)paramSpec; - result += " (" + nc.getNameAndAliases()[0] + ")"; - } - } else if (key instanceof EdECKey) { - result = ((EdECKey) key).getParams().getName(); - } - return result; - } - private String withWeakConstraint(Key key, CertPathConstraintsParameters cpcp) { int kLen = KeyUtil.getKeySize(key); - String displayAlg = fullDisplayAlgName(key); + String displayAlg = KeyUtil.fullDisplayAlgName(key); try { DISABLED_CHECK.permits(key.getAlgorithm(), cpcp, true); } catch (CertPathValidatorException e) { @@ -4944,13 +4930,13 @@ public final class Main { weakWarnings.add(String.format( rb.getString("whose.key.weak"), label, String.format(rb.getString("key.bit"), - KeyUtil.getKeySize(key), fullDisplayAlgName(key)))); + KeyUtil.getKeySize(key), KeyUtil.fullDisplayAlgName(key)))); } } catch (CertPathValidatorException e) { weakWarnings.add(String.format( rb.getString("whose.key.disabled"), label, String.format(rb.getString("key.bit"), - KeyUtil.getKeySize(key), fullDisplayAlgName(key)))); + KeyUtil.getKeySize(key), KeyUtil.fullDisplayAlgName(key)))); } } } @@ -4971,12 +4957,12 @@ public final class Main { weakWarnings.add(String.format( rb.getString("whose.key.disabled"), label, String.format(rb.getString("key.bit"), - KeyUtil.getKeySize(key), fullDisplayAlgName(key)))); + KeyUtil.getKeySize(key), KeyUtil.fullDisplayAlgName(key)))); } else if (!LEGACY_CHECK.permits(SIG_PRIMITIVE_SET, key)) { weakWarnings.add(String.format( rb.getString("whose.key.weak"), label, String.format(rb.getString("key.bit"), - KeyUtil.getKeySize(key), fullDisplayAlgName(key)))); + KeyUtil.getKeySize(key), KeyUtil.fullDisplayAlgName(key)))); } } } diff --git a/src/java.base/share/classes/sun/security/util/DisabledAlgorithmConstraints.java b/src/java.base/share/classes/sun/security/util/DisabledAlgorithmConstraints.java index 03e9cf6a2c6308de01362dac7a6614d7ee02eeb2..0cdb85decaf2083606a0bf7e5b07ad1d15fc6795 100644 --- a/src/java.base/share/classes/sun/security/util/DisabledAlgorithmConstraints.java +++ b/src/java.base/share/classes/sun/security/util/DisabledAlgorithmConstraints.java @@ -202,7 +202,7 @@ public class DisabledAlgorithmConstraints extends AbstractAlgorithmConstraints { } } - private void permits(AlgorithmParameters ap, ConstraintsParameters cp) + public void permits(AlgorithmParameters ap, ConstraintsParameters cp) throws CertPathValidatorException { switch (ap.getAlgorithm().toUpperCase(Locale.ENGLISH)) { @@ -783,7 +783,7 @@ public class DisabledAlgorithmConstraints extends AbstractAlgorithmConstraints { for (String usage : usages) { boolean match = false; - switch (usage.toLowerCase()) { + switch (usage.toLowerCase(Locale.ENGLISH)) { case "tlsserver": match = variant.equals(Validator.VAR_TLS_SERVER); break; diff --git a/src/java.base/share/classes/sun/security/util/ECParameters.java b/src/java.base/share/classes/sun/security/util/ECParameters.java index 317fad31ce4e92f74602ea5565e7da644f057758..429b022cc1baa9a21ccae8dd20fc2fdadc522e28 100644 --- a/src/java.base/share/classes/sun/security/util/ECParameters.java +++ b/src/java.base/share/classes/sun/security/util/ECParameters.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, 2014, 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 @@ -122,8 +122,9 @@ public final class ECParameters extends AlgorithmParametersSpi { int keySize = ((ECKeySizeParameterSpec)paramSpec).getKeySize(); namedCurve = CurveDB.lookup(keySize); } else { - throw new InvalidParameterSpecException - ("Only ECParameterSpec and ECGenParameterSpec supported"); + throw new InvalidParameterSpecException( + "Only ECParameterSpec, ECGenParameterSpec " + + "and ECKeySizeParameterSpec supported"); } if (namedCurve == null) { @@ -213,7 +214,8 @@ public final class ECParameters extends AlgorithmParametersSpi { } throw new InvalidParameterSpecException( - "Only ECParameterSpec and ECGenParameterSpec supported"); + "Only ECParameterSpec, ECGenParameterSpec " + + "and ECKeySizeParameterSpec supported"); } protected byte[] engineGetEncoded() throws IOException { @@ -233,4 +235,3 @@ public final class ECParameters extends AlgorithmParametersSpi { return namedCurve.toString(); } } - diff --git a/src/java.base/share/classes/sun/security/util/HostnameChecker.java b/src/java.base/share/classes/sun/security/util/HostnameChecker.java index aacd94837c962cb92ad48c6ced680539886e84f6..4c0bca36830706a8b9c695a7410ea311dd45c27d 100644 --- a/src/java.base/share/classes/sun/security/util/HostnameChecker.java +++ b/src/java.base/share/classes/sun/security/util/HostnameChecker.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 @@ -178,7 +178,7 @@ public class HostnameChecker { * Certification Authorities are encouraged to use the dNSName instead. * * Matching is performed using the matching rules specified by - * [RFC5280]. If more than one identity of a given type is present in + * [RFC6125]. If more than one identity of a given type is present in * the certificate (e.g., more than one dNSName name, a match in any one * of the set is considered acceptable.) */ @@ -262,7 +262,7 @@ public class HostnameChecker { /** * Returns true if name matches against template.

      * - * The matching is performed as per RFC 2818 rules for TLS and + * The matching is performed as per RFC 2818/6125 rules for TLS and * RFC 2830 rules for LDAP.

      * * The name parameter should represent a DNS name. The @@ -299,9 +299,7 @@ public class HostnameChecker { return false; } - if (checkType == TYPE_TLS) { - return matchAllWildcards(name, template); - } else if (checkType == TYPE_LDAP) { + if (checkType == TYPE_TLS || checkType == TYPE_LDAP) { return matchLeftmostWildcard(name, template); } else { return false; @@ -371,37 +369,6 @@ public class HostnameChecker { return false; } - /** - * Returns true if name matches against template.

      - * - * According to RFC 2818, section 3.1 - - * Names may contain the wildcard character * which is - * considered to match any single domain name component - * or component fragment. - * E.g., *.a.com matches foo.a.com but not - * bar.foo.a.com. f*.com matches foo.com but not bar.com. - */ - private static boolean matchAllWildcards(String name, - String template) { - name = name.toLowerCase(Locale.ENGLISH); - template = template.toLowerCase(Locale.ENGLISH); - StringTokenizer nameSt = new StringTokenizer(name, "."); - StringTokenizer templateSt = new StringTokenizer(template, "."); - - if (nameSt.countTokens() != templateSt.countTokens()) { - return false; - } - - while (nameSt.hasMoreTokens()) { - if (!matchWildCards(nameSt.nextToken(), - templateSt.nextToken())) { - return false; - } - } - return true; - } - - /** * Returns true if name matches against template.

      * diff --git a/src/java.base/share/classes/sun/security/util/KeyUtil.java b/src/java.base/share/classes/sun/security/util/KeyUtil.java index a20ebffa5ff53a72ffd38633307cf588150990b6..3648447e10e138616d30c086781d2bb83b8e8547 100644 --- a/src/java.base/share/classes/sun/security/util/KeyUtil.java +++ b/src/java.base/share/classes/sun/security/util/KeyUtil.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 @@ -190,6 +190,28 @@ public final class KeyUtil { return -1; } + /** + * Returns the algorithm name of the given key object. If an EC key is + * specified, returns the algorithm name and its named curve. + * + * @param key the key object, cannot be null + * @return the algorithm name of the given key object, or return in the + * form of "EC (named curve)" if the given key object is an EC key + */ + public static final String fullDisplayAlgName(Key key) { + String result = key.getAlgorithm(); + if (key instanceof ECKey) { + ECParameterSpec paramSpec = ((ECKey) key).getParams(); + if (paramSpec instanceof NamedCurve) { + NamedCurve nc = (NamedCurve)paramSpec; + result += " (" + nc.getNameAndAliases()[0] + ")"; + } + } else if (key instanceof EdECKey) { + result = ((EdECKey) key).getParams().getName(); + } + return result; + } + /** * Returns whether the key is valid or not. *

      diff --git a/src/java.base/share/classes/sun/security/util/SecurityProviderConstants.java b/src/java.base/share/classes/sun/security/util/SecurityProviderConstants.java index ed826dff24ae49028796a944a82773e58af86600..166c4a5130f7c1efa024bac6c164d31a7979a4fb 100644 --- a/src/java.base/share/classes/sun/security/util/SecurityProviderConstants.java +++ b/src/java.base/share/classes/sun/security/util/SecurityProviderConstants.java @@ -140,7 +140,8 @@ public final class SecurityProviderConstants { } continue; } - String algoName = algoAndValue[0].trim().toUpperCase(); + String algoName = + algoAndValue[0].trim().toUpperCase(Locale.ENGLISH); int value = -1; try { value = Integer.parseInt(algoAndValue[1].trim()); diff --git a/src/java.base/share/classes/sun/security/util/SignatureFileVerifier.java b/src/java.base/share/classes/sun/security/util/SignatureFileVerifier.java index d07152eeb18beb17515c27007f711f46e7ffcfe1..6cc86b03b505190df32357814c755a105111cc6d 100644 --- a/src/java.base/share/classes/sun/security/util/SignatureFileVerifier.java +++ b/src/java.base/share/classes/sun/security/util/SignatureFileVerifier.java @@ -386,7 +386,8 @@ public class SignatureFileVerifier { .jarConstraints().permits(algorithm, params, false); } catch (GeneralSecurityException e) { permittedAlgs.put(algorithm, Boolean.FALSE); - permittedAlgs.put(key.toUpperCase(), Boolean.FALSE); + permittedAlgs.put(key.toUpperCase(Locale.ENGLISH), + Boolean.FALSE); if (debug != null) { if (e.getMessage() != null) { debug.println(key + ": " + e.getMessage()); diff --git a/src/java.base/share/classes/sun/security/util/SignatureUtil.java b/src/java.base/share/classes/sun/security/util/SignatureUtil.java index 7266339c9774f1444be25706a612603966d032c5..ec86df854fcc50827614f152f89bf31dc0dc8c2c 100644 --- a/src/java.base/share/classes/sun/security/util/SignatureUtil.java +++ b/src/java.base/share/classes/sun/security/util/SignatureUtil.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,32 +47,39 @@ import sun.security.x509.AlgorithmId; public class SignatureUtil { /** - * Convert OID.1.2.3.4 or 1.2.3.4 to its matching stdName. + * Convert OID.1.2.3.4 or 1.2.3.4 to its matching stdName, and return + * upper case algorithm name. * * @param algName input, could be in any form - * @return the matching stdName, or {@code algName} if it is not in the - * form of an OID, or the OID value if no match is found. + * @return the matching algorithm name or the OID string in upper case. */ private static String checkName(String algName) { - if (!algName.contains(".")) { - return algName; - } else { + algName = algName.toUpperCase(Locale.ENGLISH); + if (algName.contains(".")) { // convert oid to String if (algName.startsWith("OID.")) { algName = algName.substring(4); } + KnownOIDs ko = KnownOIDs.findMatch(algName); - return ko != null ? ko.stdName() : algName; + if (ko != null) { + return ko.stdName().toUpperCase(Locale.ENGLISH); + } } + + return algName; } // Utility method of creating an AlgorithmParameters object with // the specified algorithm name and encoding + // + // Note this method can be called only after converting OID.1.2.3.4 or + // 1.2.3.4 to its matching stdName, which is implemented in the + // checkName(String) method. private static AlgorithmParameters createAlgorithmParameters(String algName, byte[] paramBytes) throws ProviderException { try { - algName = checkName(algName); AlgorithmParameters result = AlgorithmParameters.getInstance(algName); result.init(paramBytes); @@ -96,7 +103,7 @@ public class SignatureUtil { AlgorithmParameterSpec paramSpec = null; if (params != null) { - sigName = checkName(sigName).toUpperCase(Locale.ENGLISH); + sigName = checkName(sigName); // AlgorithmParameters.getAlgorithm() may returns oid if it's // created during DER decoding. Convert to use the standard name // before passing it to RSAUtil @@ -140,7 +147,7 @@ public class SignatureUtil { AlgorithmParameterSpec paramSpec = null; if (paramBytes != null) { - sigName = checkName(sigName).toUpperCase(Locale.ENGLISH); + sigName = checkName(sigName); if (sigName.contains("RSA")) { AlgorithmParameters params = createAlgorithmParameters(sigName, paramBytes); @@ -313,7 +320,7 @@ public class SignatureUtil { public static AlgorithmParameterSpec getDefaultParamSpec( String sigAlg, Key k) { sigAlg = checkName(sigAlg); - if (sigAlg.equalsIgnoreCase("RSASSA-PSS")) { + if (sigAlg.equals("RSASSA-PSS")) { if (k instanceof RSAKey) { AlgorithmParameterSpec spec = ((RSAKey) k).getParams(); if (spec instanceof PSSParameterSpec) { @@ -428,7 +435,7 @@ public class SignatureUtil { */ public static void checkKeyAndSigAlgMatch(PrivateKey key, String sAlg) { String kAlg = key.getAlgorithm().toUpperCase(Locale.ENGLISH); - sAlg = checkName(sAlg).toUpperCase(Locale.ENGLISH); + sAlg = checkName(sAlg); switch (sAlg) { case "RSASSA-PSS" -> { if (!kAlg.equals("RSASSA-PSS") diff --git a/src/java.base/share/classes/sun/security/util/TlsChannelBinding.java b/src/java.base/share/classes/sun/security/util/TlsChannelBinding.java index 8f7ac50bb5e761087bf609b2010aa5d5b5c1b3cd..fffd4fa6707c4c08367e0dc30288bbe33de1cb60 100644 --- a/src/java.base/share/classes/sun/security/util/TlsChannelBinding.java +++ b/src/java.base/share/classes/sun/security/util/TlsChannelBinding.java @@ -31,6 +31,7 @@ import java.security.cert.CertificateEncodingException; import java.security.cert.X509Certificate; import java.util.Arrays; import java.util.Hashtable; +import java.util.Locale; /** * This class implements the Channel Binding for TLS as defined in @@ -101,7 +102,7 @@ public class TlsChannelBinding { final byte[] prefix = TlsChannelBindingType.TLS_SERVER_END_POINT.getName().concat(":").getBytes(); String hashAlg = serverCertificate.getSigAlgName(). - replace("SHA", "SHA-").toUpperCase(); + toUpperCase(Locale.ENGLISH).replace("SHA", "SHA-"); int ind = hashAlg.indexOf("WITH"); if (ind > 0) { hashAlg = hashAlg.substring(0, ind); diff --git a/src/java.base/share/classes/sun/security/x509/OtherName.java b/src/java.base/share/classes/sun/security/x509/OtherName.java index 0a2842a00be9a9f7dcc2ec16aaaf382ae527ab66..f274a221dd4efbeccad361eb3c4c4e9b85cbba77 100644 --- a/src/java.base/share/classes/sun/security/x509/OtherName.java +++ b/src/java.base/share/classes/sun/security/x509/OtherName.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2015, 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 @@ -48,10 +48,10 @@ import sun.security.util.*; */ public class OtherName implements GeneralNameInterface { - private String name; - private ObjectIdentifier oid; - private byte[] nameValue = null; - private GeneralNameInterface gni = null; + private final ObjectIdentifier oid; + private final String name; + private final byte[] nameValue; // value inside [0] + private final GeneralNameInterface gni; private static final byte TAG_VALUE = 0; @@ -89,8 +89,12 @@ public class OtherName implements GeneralNameInterface { DerInputStream in = derValue.toDerInputStream(); oid = in.getOID(); - DerValue val = in.getDerValue(); - nameValue = val.toByteArray(); + DerValue derValue1 = in.getDerValue(); + if (derValue1.isContextSpecific((byte) 0) && derValue1.isConstructed()) { + nameValue = derValue1.data.toByteArray(); + } else { + throw new IOException("value is not EXPLICTly tagged [0]"); + } gni = getGNI(oid, nameValue); if (gni != null) { name = gni.toString(); @@ -125,12 +129,13 @@ public class OtherName implements GeneralNameInterface { return null; } Class[] params = { Object.class }; - Constructor cons = extClass.getConstructor(params); - - Object[] passed = new Object[] { nameValue }; - GeneralNameInterface gni = - (GeneralNameInterface)cons.newInstance(passed); - return gni; + Constructor cons; + try { + cons = extClass.getConstructor(Object.class); + } catch (NoSuchMethodException e) { + cons = extClass.getConstructor(byte[].class); + } + return (GeneralNameInterface)cons.newInstance(nameValue); } catch (Exception e) { throw new IOException("Instantiation error: " + e, e); } diff --git a/src/java.base/share/classes/sun/security/x509/X509CertImpl.java b/src/java.base/share/classes/sun/security/x509/X509CertImpl.java index 3a1817327f9624fc09cbedd11f7b15d9f2e50b61..103c9f86b84823b725554f9f2490d0b5fde6a9ff 100644 --- a/src/java.base/share/classes/sun/security/x509/X509CertImpl.java +++ b/src/java.base/share/classes/sun/security/x509/X509CertImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -1584,6 +1584,17 @@ public class X509CertImpl extends X509Certificate implements DerEncoder { throw new RuntimeException("name cannot be encoded", ioe); } nameEntry.add(derOut.toByteArray()); + if (name.getType() == GeneralNameInterface.NAME_ANY + && name instanceof OtherName oname) { + nameEntry.add(oname.getOID().toString()); + byte[] nameValue = oname.getNameValue(); + try { + String v = new DerValue(nameValue).getAsString(); + nameEntry.add(v == null ? nameValue : v); + } catch (IOException ioe) { + nameEntry.add(nameValue); + } + } break; } newNames.add(Collections.unmodifiableList(nameEntry)); diff --git a/src/java.base/share/classes/sun/util/logging/PlatformLogger.java b/src/java.base/share/classes/sun/util/logging/PlatformLogger.java index 07c6878c15115aac69a32468757e9e4b64c7365b..db85d9c317b9f518e2682c12aba902326192a22a 100644 --- a/src/java.base/share/classes/sun/util/logging/PlatformLogger.java +++ b/src/java.base/share/classes/sun/util/logging/PlatformLogger.java @@ -371,7 +371,7 @@ public class PlatformLogger { @Deprecated public void setLevel(Level newLevel) { final ConfigurableBridge.LoggerConfiguration spi = - PlatformLogger.ConfigurableBridge.getLoggerConfiguration(loggerProxy);; + PlatformLogger.ConfigurableBridge.getLoggerConfiguration(loggerProxy); if (spi != null) { spi.setPlatformLevel(newLevel); } diff --git a/src/java.base/share/classes/sun/util/resources/CurrencyNames.properties b/src/java.base/share/classes/sun/util/resources/CurrencyNames.properties index 9f1867d2cd1ed3fbb41c2294354746815c3a3b1d..53bf1d837ff60416255503277dba683c6c4c249a 100644 --- a/src/java.base/share/classes/sun/util/resources/CurrencyNames.properties +++ b/src/java.base/share/classes/sun/util/resources/CurrencyNames.properties @@ -1,5 +1,5 @@ # -# Copyright (c) 2005, 2021, 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 @@ -221,6 +221,7 @@ SGD=SGD SHP=SHP SIT=SIT SKK=SKK +SLE=SLE SLL=SLL SOS=SOS SRD=SRD @@ -445,6 +446,7 @@ sgd=Singapore Dollar shp=Saint Helena Pound sit=Slovenian Tolar skk=Slovak Koruna +sle=Sierra Leonean Leone sll=Sierra Leonean Leone sos=Somali Shilling srd=Surinamese Dollar diff --git a/make/data/blockedcertsconverter/blocked.certs.pem b/src/java.base/share/data/blockedcertsconverter/blocked.certs.pem similarity index 100% rename from make/data/blockedcertsconverter/blocked.certs.pem rename to src/java.base/share/data/blockedcertsconverter/blocked.certs.pem diff --git a/make/data/cacerts/README b/src/java.base/share/data/cacerts/README similarity index 100% rename from make/data/cacerts/README rename to src/java.base/share/data/cacerts/README diff --git a/make/data/cacerts/actalisauthenticationrootca b/src/java.base/share/data/cacerts/actalisauthenticationrootca similarity index 100% rename from make/data/cacerts/actalisauthenticationrootca rename to src/java.base/share/data/cacerts/actalisauthenticationrootca diff --git a/make/data/cacerts/addtrustexternalca b/src/java.base/share/data/cacerts/addtrustexternalca similarity index 100% rename from make/data/cacerts/addtrustexternalca rename to src/java.base/share/data/cacerts/addtrustexternalca diff --git a/make/data/cacerts/addtrustqualifiedca b/src/java.base/share/data/cacerts/addtrustqualifiedca similarity index 100% rename from make/data/cacerts/addtrustqualifiedca rename to src/java.base/share/data/cacerts/addtrustqualifiedca diff --git a/make/data/cacerts/affirmtrustcommercialca b/src/java.base/share/data/cacerts/affirmtrustcommercialca similarity index 100% rename from make/data/cacerts/affirmtrustcommercialca rename to src/java.base/share/data/cacerts/affirmtrustcommercialca diff --git a/make/data/cacerts/affirmtrustnetworkingca b/src/java.base/share/data/cacerts/affirmtrustnetworkingca similarity index 100% rename from make/data/cacerts/affirmtrustnetworkingca rename to src/java.base/share/data/cacerts/affirmtrustnetworkingca diff --git a/make/data/cacerts/affirmtrustpremiumca b/src/java.base/share/data/cacerts/affirmtrustpremiumca similarity index 100% rename from make/data/cacerts/affirmtrustpremiumca rename to src/java.base/share/data/cacerts/affirmtrustpremiumca diff --git a/make/data/cacerts/affirmtrustpremiumeccca b/src/java.base/share/data/cacerts/affirmtrustpremiumeccca similarity index 100% rename from make/data/cacerts/affirmtrustpremiumeccca rename to src/java.base/share/data/cacerts/affirmtrustpremiumeccca diff --git a/make/data/cacerts/amazonrootca1 b/src/java.base/share/data/cacerts/amazonrootca1 similarity index 100% rename from make/data/cacerts/amazonrootca1 rename to src/java.base/share/data/cacerts/amazonrootca1 diff --git a/make/data/cacerts/amazonrootca2 b/src/java.base/share/data/cacerts/amazonrootca2 similarity index 100% rename from make/data/cacerts/amazonrootca2 rename to src/java.base/share/data/cacerts/amazonrootca2 diff --git a/make/data/cacerts/amazonrootca3 b/src/java.base/share/data/cacerts/amazonrootca3 similarity index 100% rename from make/data/cacerts/amazonrootca3 rename to src/java.base/share/data/cacerts/amazonrootca3 diff --git a/make/data/cacerts/amazonrootca4 b/src/java.base/share/data/cacerts/amazonrootca4 similarity index 100% rename from make/data/cacerts/amazonrootca4 rename to src/java.base/share/data/cacerts/amazonrootca4 diff --git a/make/data/cacerts/baltimorecybertrustca b/src/java.base/share/data/cacerts/baltimorecybertrustca similarity index 100% rename from make/data/cacerts/baltimorecybertrustca rename to src/java.base/share/data/cacerts/baltimorecybertrustca diff --git a/make/data/cacerts/buypassclass2ca b/src/java.base/share/data/cacerts/buypassclass2ca similarity index 100% rename from make/data/cacerts/buypassclass2ca rename to src/java.base/share/data/cacerts/buypassclass2ca diff --git a/make/data/cacerts/buypassclass3ca b/src/java.base/share/data/cacerts/buypassclass3ca similarity index 100% rename from make/data/cacerts/buypassclass3ca rename to src/java.base/share/data/cacerts/buypassclass3ca diff --git a/make/data/cacerts/camerfirmachambersca b/src/java.base/share/data/cacerts/camerfirmachambersca similarity index 100% rename from make/data/cacerts/camerfirmachambersca rename to src/java.base/share/data/cacerts/camerfirmachambersca diff --git a/make/data/cacerts/camerfirmachamberscommerceca b/src/java.base/share/data/cacerts/camerfirmachamberscommerceca similarity index 100% rename from make/data/cacerts/camerfirmachamberscommerceca rename to src/java.base/share/data/cacerts/camerfirmachamberscommerceca diff --git a/make/data/cacerts/camerfirmachambersignca b/src/java.base/share/data/cacerts/camerfirmachambersignca similarity index 100% rename from make/data/cacerts/camerfirmachambersignca rename to src/java.base/share/data/cacerts/camerfirmachambersignca diff --git a/make/data/cacerts/certumca b/src/java.base/share/data/cacerts/certumca similarity index 100% rename from make/data/cacerts/certumca rename to src/java.base/share/data/cacerts/certumca diff --git a/make/data/cacerts/certumtrustednetworkca b/src/java.base/share/data/cacerts/certumtrustednetworkca similarity index 100% rename from make/data/cacerts/certumtrustednetworkca rename to src/java.base/share/data/cacerts/certumtrustednetworkca diff --git a/make/data/cacerts/chunghwaepkirootca b/src/java.base/share/data/cacerts/chunghwaepkirootca similarity index 100% rename from make/data/cacerts/chunghwaepkirootca rename to src/java.base/share/data/cacerts/chunghwaepkirootca diff --git a/make/data/cacerts/comodoaaaca b/src/java.base/share/data/cacerts/comodoaaaca similarity index 100% rename from make/data/cacerts/comodoaaaca rename to src/java.base/share/data/cacerts/comodoaaaca diff --git a/make/data/cacerts/comodoeccca b/src/java.base/share/data/cacerts/comodoeccca similarity index 100% rename from make/data/cacerts/comodoeccca rename to src/java.base/share/data/cacerts/comodoeccca diff --git a/make/data/cacerts/comodorsaca b/src/java.base/share/data/cacerts/comodorsaca similarity index 100% rename from make/data/cacerts/comodorsaca rename to src/java.base/share/data/cacerts/comodorsaca diff --git a/make/data/cacerts/digicertassuredidg2 b/src/java.base/share/data/cacerts/digicertassuredidg2 similarity index 100% rename from make/data/cacerts/digicertassuredidg2 rename to src/java.base/share/data/cacerts/digicertassuredidg2 diff --git a/make/data/cacerts/digicertassuredidg3 b/src/java.base/share/data/cacerts/digicertassuredidg3 similarity index 100% rename from make/data/cacerts/digicertassuredidg3 rename to src/java.base/share/data/cacerts/digicertassuredidg3 diff --git a/make/data/cacerts/digicertassuredidrootca b/src/java.base/share/data/cacerts/digicertassuredidrootca similarity index 100% rename from make/data/cacerts/digicertassuredidrootca rename to src/java.base/share/data/cacerts/digicertassuredidrootca diff --git a/make/data/cacerts/digicertglobalrootca b/src/java.base/share/data/cacerts/digicertglobalrootca similarity index 100% rename from make/data/cacerts/digicertglobalrootca rename to src/java.base/share/data/cacerts/digicertglobalrootca diff --git a/make/data/cacerts/digicertglobalrootg2 b/src/java.base/share/data/cacerts/digicertglobalrootg2 similarity index 100% rename from make/data/cacerts/digicertglobalrootg2 rename to src/java.base/share/data/cacerts/digicertglobalrootg2 diff --git a/make/data/cacerts/digicertglobalrootg3 b/src/java.base/share/data/cacerts/digicertglobalrootg3 similarity index 100% rename from make/data/cacerts/digicertglobalrootg3 rename to src/java.base/share/data/cacerts/digicertglobalrootg3 diff --git a/make/data/cacerts/digicerthighassuranceevrootca b/src/java.base/share/data/cacerts/digicerthighassuranceevrootca similarity index 100% rename from make/data/cacerts/digicerthighassuranceevrootca rename to src/java.base/share/data/cacerts/digicerthighassuranceevrootca diff --git a/make/data/cacerts/digicerttrustedrootg4 b/src/java.base/share/data/cacerts/digicerttrustedrootg4 similarity index 100% rename from make/data/cacerts/digicerttrustedrootg4 rename to src/java.base/share/data/cacerts/digicerttrustedrootg4 diff --git a/make/data/cacerts/dtrustclass3ca2 b/src/java.base/share/data/cacerts/dtrustclass3ca2 similarity index 100% rename from make/data/cacerts/dtrustclass3ca2 rename to src/java.base/share/data/cacerts/dtrustclass3ca2 diff --git a/make/data/cacerts/dtrustclass3ca2ev b/src/java.base/share/data/cacerts/dtrustclass3ca2ev similarity index 100% rename from make/data/cacerts/dtrustclass3ca2ev rename to src/java.base/share/data/cacerts/dtrustclass3ca2ev diff --git a/make/data/cacerts/entrust2048ca b/src/java.base/share/data/cacerts/entrust2048ca similarity index 100% rename from make/data/cacerts/entrust2048ca rename to src/java.base/share/data/cacerts/entrust2048ca diff --git a/make/data/cacerts/entrustevca b/src/java.base/share/data/cacerts/entrustevca similarity index 100% rename from make/data/cacerts/entrustevca rename to src/java.base/share/data/cacerts/entrustevca diff --git a/make/data/cacerts/entrustrootcaec1 b/src/java.base/share/data/cacerts/entrustrootcaec1 similarity index 100% rename from make/data/cacerts/entrustrootcaec1 rename to src/java.base/share/data/cacerts/entrustrootcaec1 diff --git a/make/data/cacerts/entrustrootcag2 b/src/java.base/share/data/cacerts/entrustrootcag2 similarity index 100% rename from make/data/cacerts/entrustrootcag2 rename to src/java.base/share/data/cacerts/entrustrootcag2 diff --git a/make/data/cacerts/entrustrootcag4 b/src/java.base/share/data/cacerts/entrustrootcag4 similarity index 100% rename from make/data/cacerts/entrustrootcag4 rename to src/java.base/share/data/cacerts/entrustrootcag4 diff --git a/make/data/cacerts/geotrustglobalca b/src/java.base/share/data/cacerts/geotrustglobalca similarity index 100% rename from make/data/cacerts/geotrustglobalca rename to src/java.base/share/data/cacerts/geotrustglobalca diff --git a/make/data/cacerts/geotrustprimaryca b/src/java.base/share/data/cacerts/geotrustprimaryca similarity index 100% rename from make/data/cacerts/geotrustprimaryca rename to src/java.base/share/data/cacerts/geotrustprimaryca diff --git a/make/data/cacerts/geotrustprimarycag2 b/src/java.base/share/data/cacerts/geotrustprimarycag2 similarity index 100% rename from make/data/cacerts/geotrustprimarycag2 rename to src/java.base/share/data/cacerts/geotrustprimarycag2 diff --git a/make/data/cacerts/geotrustprimarycag3 b/src/java.base/share/data/cacerts/geotrustprimarycag3 similarity index 100% rename from make/data/cacerts/geotrustprimarycag3 rename to src/java.base/share/data/cacerts/geotrustprimarycag3 diff --git a/make/data/cacerts/geotrustuniversalca b/src/java.base/share/data/cacerts/geotrustuniversalca similarity index 100% rename from make/data/cacerts/geotrustuniversalca rename to src/java.base/share/data/cacerts/geotrustuniversalca diff --git a/make/data/cacerts/globalsignca b/src/java.base/share/data/cacerts/globalsignca similarity index 100% rename from make/data/cacerts/globalsignca rename to src/java.base/share/data/cacerts/globalsignca diff --git a/make/data/cacerts/globalsigneccrootcar4 b/src/java.base/share/data/cacerts/globalsigneccrootcar4 similarity index 100% rename from make/data/cacerts/globalsigneccrootcar4 rename to src/java.base/share/data/cacerts/globalsigneccrootcar4 diff --git a/make/data/cacerts/globalsigneccrootcar5 b/src/java.base/share/data/cacerts/globalsigneccrootcar5 similarity index 100% rename from make/data/cacerts/globalsigneccrootcar5 rename to src/java.base/share/data/cacerts/globalsigneccrootcar5 diff --git a/make/data/cacerts/globalsignr3ca b/src/java.base/share/data/cacerts/globalsignr3ca similarity index 100% rename from make/data/cacerts/globalsignr3ca rename to src/java.base/share/data/cacerts/globalsignr3ca diff --git a/make/data/cacerts/globalsignrootcar6 b/src/java.base/share/data/cacerts/globalsignrootcar6 similarity index 100% rename from make/data/cacerts/globalsignrootcar6 rename to src/java.base/share/data/cacerts/globalsignrootcar6 diff --git a/make/data/cacerts/godaddyclass2ca b/src/java.base/share/data/cacerts/godaddyclass2ca similarity index 100% rename from make/data/cacerts/godaddyclass2ca rename to src/java.base/share/data/cacerts/godaddyclass2ca diff --git a/make/data/cacerts/godaddyrootg2ca b/src/java.base/share/data/cacerts/godaddyrootg2ca similarity index 100% rename from make/data/cacerts/godaddyrootg2ca rename to src/java.base/share/data/cacerts/godaddyrootg2ca diff --git a/make/data/cacerts/haricaeccrootca2015 b/src/java.base/share/data/cacerts/haricaeccrootca2015 similarity index 100% rename from make/data/cacerts/haricaeccrootca2015 rename to src/java.base/share/data/cacerts/haricaeccrootca2015 diff --git a/make/data/cacerts/haricarootca2015 b/src/java.base/share/data/cacerts/haricarootca2015 similarity index 100% rename from make/data/cacerts/haricarootca2015 rename to src/java.base/share/data/cacerts/haricarootca2015 diff --git a/make/data/cacerts/identrustcommercial b/src/java.base/share/data/cacerts/identrustcommercial similarity index 100% rename from make/data/cacerts/identrustcommercial rename to src/java.base/share/data/cacerts/identrustcommercial diff --git a/make/data/cacerts/identrustpublicca b/src/java.base/share/data/cacerts/identrustpublicca similarity index 100% rename from make/data/cacerts/identrustpublicca rename to src/java.base/share/data/cacerts/identrustpublicca diff --git a/make/data/cacerts/letsencryptisrgx1 b/src/java.base/share/data/cacerts/letsencryptisrgx1 similarity index 100% rename from make/data/cacerts/letsencryptisrgx1 rename to src/java.base/share/data/cacerts/letsencryptisrgx1 diff --git a/make/data/cacerts/luxtrustglobalroot2ca b/src/java.base/share/data/cacerts/luxtrustglobalroot2ca similarity index 100% rename from make/data/cacerts/luxtrustglobalroot2ca rename to src/java.base/share/data/cacerts/luxtrustglobalroot2ca diff --git a/make/data/cacerts/luxtrustglobalrootca b/src/java.base/share/data/cacerts/luxtrustglobalrootca similarity index 100% rename from make/data/cacerts/luxtrustglobalrootca rename to src/java.base/share/data/cacerts/luxtrustglobalrootca diff --git a/make/data/cacerts/quovadisrootca b/src/java.base/share/data/cacerts/quovadisrootca similarity index 100% rename from make/data/cacerts/quovadisrootca rename to src/java.base/share/data/cacerts/quovadisrootca diff --git a/make/data/cacerts/quovadisrootca1g3 b/src/java.base/share/data/cacerts/quovadisrootca1g3 similarity index 100% rename from make/data/cacerts/quovadisrootca1g3 rename to src/java.base/share/data/cacerts/quovadisrootca1g3 diff --git a/make/data/cacerts/quovadisrootca2 b/src/java.base/share/data/cacerts/quovadisrootca2 similarity index 100% rename from make/data/cacerts/quovadisrootca2 rename to src/java.base/share/data/cacerts/quovadisrootca2 diff --git a/make/data/cacerts/quovadisrootca2g3 b/src/java.base/share/data/cacerts/quovadisrootca2g3 similarity index 100% rename from make/data/cacerts/quovadisrootca2g3 rename to src/java.base/share/data/cacerts/quovadisrootca2g3 diff --git a/make/data/cacerts/quovadisrootca3 b/src/java.base/share/data/cacerts/quovadisrootca3 similarity index 100% rename from make/data/cacerts/quovadisrootca3 rename to src/java.base/share/data/cacerts/quovadisrootca3 diff --git a/make/data/cacerts/quovadisrootca3g3 b/src/java.base/share/data/cacerts/quovadisrootca3g3 similarity index 100% rename from make/data/cacerts/quovadisrootca3g3 rename to src/java.base/share/data/cacerts/quovadisrootca3g3 diff --git a/make/data/cacerts/secomscrootca1 b/src/java.base/share/data/cacerts/secomscrootca1 similarity index 100% rename from make/data/cacerts/secomscrootca1 rename to src/java.base/share/data/cacerts/secomscrootca1 diff --git a/make/data/cacerts/secomscrootca2 b/src/java.base/share/data/cacerts/secomscrootca2 similarity index 100% rename from make/data/cacerts/secomscrootca2 rename to src/java.base/share/data/cacerts/secomscrootca2 diff --git a/make/data/cacerts/securetrustca b/src/java.base/share/data/cacerts/securetrustca similarity index 100% rename from make/data/cacerts/securetrustca rename to src/java.base/share/data/cacerts/securetrustca diff --git a/make/data/cacerts/sslrooteccca b/src/java.base/share/data/cacerts/sslrooteccca similarity index 100% rename from make/data/cacerts/sslrooteccca rename to src/java.base/share/data/cacerts/sslrooteccca diff --git a/make/data/cacerts/sslrootevrsaca b/src/java.base/share/data/cacerts/sslrootevrsaca similarity index 100% rename from make/data/cacerts/sslrootevrsaca rename to src/java.base/share/data/cacerts/sslrootevrsaca diff --git a/make/data/cacerts/sslrootrsaca b/src/java.base/share/data/cacerts/sslrootrsaca similarity index 100% rename from make/data/cacerts/sslrootrsaca rename to src/java.base/share/data/cacerts/sslrootrsaca diff --git a/make/data/cacerts/starfieldclass2ca b/src/java.base/share/data/cacerts/starfieldclass2ca similarity index 100% rename from make/data/cacerts/starfieldclass2ca rename to src/java.base/share/data/cacerts/starfieldclass2ca diff --git a/make/data/cacerts/starfieldrootg2ca b/src/java.base/share/data/cacerts/starfieldrootg2ca similarity index 100% rename from make/data/cacerts/starfieldrootg2ca rename to src/java.base/share/data/cacerts/starfieldrootg2ca diff --git a/make/data/cacerts/starfieldservicesrootg2ca b/src/java.base/share/data/cacerts/starfieldservicesrootg2ca similarity index 100% rename from make/data/cacerts/starfieldservicesrootg2ca rename to src/java.base/share/data/cacerts/starfieldservicesrootg2ca diff --git a/make/data/cacerts/swisssigngoldg2ca b/src/java.base/share/data/cacerts/swisssigngoldg2ca similarity index 100% rename from make/data/cacerts/swisssigngoldg2ca rename to src/java.base/share/data/cacerts/swisssigngoldg2ca diff --git a/make/data/cacerts/swisssignplatinumg2ca b/src/java.base/share/data/cacerts/swisssignplatinumg2ca similarity index 100% rename from make/data/cacerts/swisssignplatinumg2ca rename to src/java.base/share/data/cacerts/swisssignplatinumg2ca diff --git a/make/data/cacerts/swisssignsilverg2ca b/src/java.base/share/data/cacerts/swisssignsilverg2ca similarity index 100% rename from make/data/cacerts/swisssignsilverg2ca rename to src/java.base/share/data/cacerts/swisssignsilverg2ca diff --git a/make/data/cacerts/teliasonerarootcav1 b/src/java.base/share/data/cacerts/teliasonerarootcav1 similarity index 100% rename from make/data/cacerts/teliasonerarootcav1 rename to src/java.base/share/data/cacerts/teliasonerarootcav1 diff --git a/make/data/cacerts/thawteprimaryrootca b/src/java.base/share/data/cacerts/thawteprimaryrootca similarity index 100% rename from make/data/cacerts/thawteprimaryrootca rename to src/java.base/share/data/cacerts/thawteprimaryrootca diff --git a/make/data/cacerts/thawteprimaryrootcag2 b/src/java.base/share/data/cacerts/thawteprimaryrootcag2 similarity index 100% rename from make/data/cacerts/thawteprimaryrootcag2 rename to src/java.base/share/data/cacerts/thawteprimaryrootcag2 diff --git a/make/data/cacerts/thawteprimaryrootcag3 b/src/java.base/share/data/cacerts/thawteprimaryrootcag3 similarity index 100% rename from make/data/cacerts/thawteprimaryrootcag3 rename to src/java.base/share/data/cacerts/thawteprimaryrootcag3 diff --git a/make/data/cacerts/ttelesecglobalrootclass2ca b/src/java.base/share/data/cacerts/ttelesecglobalrootclass2ca similarity index 100% rename from make/data/cacerts/ttelesecglobalrootclass2ca rename to src/java.base/share/data/cacerts/ttelesecglobalrootclass2ca diff --git a/make/data/cacerts/ttelesecglobalrootclass3ca b/src/java.base/share/data/cacerts/ttelesecglobalrootclass3ca similarity index 100% rename from make/data/cacerts/ttelesecglobalrootclass3ca rename to src/java.base/share/data/cacerts/ttelesecglobalrootclass3ca diff --git a/make/data/cacerts/usertrusteccca b/src/java.base/share/data/cacerts/usertrusteccca similarity index 100% rename from make/data/cacerts/usertrusteccca rename to src/java.base/share/data/cacerts/usertrusteccca diff --git a/make/data/cacerts/usertrustrsaca b/src/java.base/share/data/cacerts/usertrustrsaca similarity index 100% rename from make/data/cacerts/usertrustrsaca rename to src/java.base/share/data/cacerts/usertrustrsaca diff --git a/make/data/cacerts/utnuserfirstobjectca b/src/java.base/share/data/cacerts/utnuserfirstobjectca similarity index 100% rename from make/data/cacerts/utnuserfirstobjectca rename to src/java.base/share/data/cacerts/utnuserfirstobjectca diff --git a/make/data/cacerts/verisignclass3g3ca b/src/java.base/share/data/cacerts/verisignclass3g3ca similarity index 100% rename from make/data/cacerts/verisignclass3g3ca rename to src/java.base/share/data/cacerts/verisignclass3g3ca diff --git a/make/data/cacerts/verisignclass3g4ca b/src/java.base/share/data/cacerts/verisignclass3g4ca similarity index 100% rename from make/data/cacerts/verisignclass3g4ca rename to src/java.base/share/data/cacerts/verisignclass3g4ca diff --git a/make/data/cacerts/verisignclass3g5ca b/src/java.base/share/data/cacerts/verisignclass3g5ca similarity index 100% rename from make/data/cacerts/verisignclass3g5ca rename to src/java.base/share/data/cacerts/verisignclass3g5ca diff --git a/make/data/cacerts/verisignuniversalrootca b/src/java.base/share/data/cacerts/verisignuniversalrootca similarity index 100% rename from make/data/cacerts/verisignuniversalrootca rename to src/java.base/share/data/cacerts/verisignuniversalrootca diff --git a/make/data/cacerts/xrampglobalca b/src/java.base/share/data/cacerts/xrampglobalca similarity index 100% rename from make/data/cacerts/xrampglobalca rename to src/java.base/share/data/cacerts/xrampglobalca diff --git a/make/data/currency/CurrencyData.properties b/src/java.base/share/data/currency/CurrencyData.properties similarity index 98% rename from make/data/currency/CurrencyData.properties rename to src/java.base/share/data/currency/CurrencyData.properties index 236e544feaf65543bac0ca05d69e55946dd31996..d86fc6ddfd41b08989e5f3cd5c2805abb76bfa68 100644 --- a/make/data/currency/CurrencyData.properties +++ b/src/java.base/share/data/currency/CurrencyData.properties @@ -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 @@ -32,7 +32,7 @@ formatVersion=3 # Version of the currency code information in this class. # It is a serial number that accompanies with each amendment. -dataVersion=170 +dataVersion=171 # List of all valid ISO 4217 currency codes. # To ensure compatibility, do not remove codes. @@ -51,7 +51,7 @@ all=ADP020-AED784-AFA004-AFN971-ALL008-AMD051-ANG532-AOA973-ARS032-ATS040-AUD036 MTL470-MUR480-MVR462-MWK454-MXN484-MXV979-MYR458-MZM508-MZN943-NAD516-NGN566-\ NIO558-NLG528-NOK578-NPR524-NZD554-OMR512-PAB590-PEN604-PGK598-PHP608-\ PKR586-PLN985-PTE620-PYG600-QAR634-ROL642-RON946-RSD941-RUB643-RUR810-RWF646-SAR682-\ - SBD090-SCR690-SDD736-SDG938-SEK752-SGD702-SHP654-SIT705-SKK703-SLL694-SOS706-\ + SBD090-SCR690-SDD736-SDG938-SEK752-SGD702-SHP654-SIT705-SKK703-SLE925-SLL694-SOS706-\ SRD968-SRG740-SSP728-STD678-STN930-SVC222-SYP760-SZL748-THB764-TJS972-TMM795-TMT934-TND788-TOP776-\ TPE626-TRL792-TRY949-TTD780-TWD901-TZS834-UAH980-UGX800-USD840-USN997-USS998-UYI940-\ UYU858-UZS860-VEB862-VED926-VEF937-VES928-VND704-VUV548-WST882-XAF950-XAG961-XAU959-XBA955-\ @@ -484,7 +484,7 @@ CS=CSD # SEYCHELLES SC=SCR # SIERRA LEONE -SL=SLL +SL=SLE # SINGAPORE SG=SGD # SLOVAKIA diff --git a/make/data/lsrdata/language-subtag-registry.txt b/src/java.base/share/data/lsrdata/language-subtag-registry.txt similarity index 100% rename from make/data/lsrdata/language-subtag-registry.txt rename to src/java.base/share/data/lsrdata/language-subtag-registry.txt diff --git a/src/java.base/share/data/publicsuffixlist/VERSION b/src/java.base/share/data/publicsuffixlist/VERSION new file mode 100644 index 0000000000000000000000000000000000000000..be9290a33fcd47ddc69c378dfb98e9c4591e31c4 --- /dev/null +++ b/src/java.base/share/data/publicsuffixlist/VERSION @@ -0,0 +1,2 @@ +Github: https://raw.githubusercontent.com/publicsuffix/list/3c213aab32b3c014f171b1673d4ce9b5cd72bf1c/public_suffix_list.dat +Date: 2021-11-27 diff --git a/make/data/publicsuffixlist/public_suffix_list.dat b/src/java.base/share/data/publicsuffixlist/public_suffix_list.dat similarity index 89% rename from make/data/publicsuffixlist/public_suffix_list.dat rename to src/java.base/share/data/publicsuffixlist/public_suffix_list.dat index 27fe1ee51b499d88b45da7b3111b6d3287a9c489..5529554d82df5d9af1a201dd3f160ce0a6cf6e95 100644 --- a/make/data/publicsuffixlist/public_suffix_list.dat +++ b/src/java.base/share/data/publicsuffixlist/public_suffix_list.dat @@ -175,17 +175,21 @@ it.ao // aq : https://en.wikipedia.org/wiki/.aq aq -// ar : https://nic.ar/nic-argentina/normativa-vigente +// ar : https://nic.ar/es/nic-argentina/normativa ar +bet.ar com.ar +coop.ar edu.ar gob.ar gov.ar int.ar mil.ar musica.ar +mutual.ar net.ar org.ar +senasa.ar tur.ar // arpa : https://en.wikipedia.org/wiki/.arpa @@ -258,7 +262,7 @@ tas.gov.au vic.gov.au wa.gov.au // 4LDs -education.tas.edu.au +// education.tas.edu.au - Removed at the request of the Department of Education Tasmania schools.nsw.edu.au // aw : https://en.wikipedia.org/wiki/.aw @@ -456,6 +460,7 @@ aju.br am.br anani.br aparecida.br +app.br arq.br art.br ato.br @@ -463,6 +468,7 @@ b.br barueri.br belem.br bhz.br +bib.br bio.br blog.br bmd.br @@ -477,14 +483,19 @@ cnt.br com.br contagem.br coop.br +coz.br cri.br cuiaba.br curitiba.br def.br +des.br +det.br +dev.br ecn.br eco.br edu.br emp.br +enf.br eng.br esp.br etc.br @@ -500,6 +511,7 @@ fot.br foz.br fst.br g12.br +geo.br ggf.br goiania.br gov.br @@ -543,6 +555,7 @@ jor.br jus.br leg.br lel.br +log.br londrina.br macapa.br maceio.br @@ -575,6 +588,7 @@ qsl.br radio.br rec.br recife.br +rep.br ribeirao.br rio.br riobranco.br @@ -585,6 +599,7 @@ santamaria.br santoandre.br saobernardo.br saogonca.br +seg.br sjc.br slg.br slz.br @@ -592,6 +607,7 @@ sorocaba.br srv.br taxi.br tc.br +tec.br teo.br the.br tmp.br @@ -722,7 +738,6 @@ gouv.ci // cl : https://www.nic.cl // Confirmed by .CL registry cl -aprendemas.cl co.cl gob.cl gov.cl @@ -827,7 +842,13 @@ gov.cu inf.cu // cv : https://en.wikipedia.org/wiki/.cv +// cv : http://www.dns.cv/tldcv_portal/do?com=DS;5446457100;111;+PAGE(4000018)+K-CAT-CODIGO(RDOM)+RCNT(100); <- registration rules cv +com.cv +edu.cv +int.cv +nome.cv +org.cv // cw : http://www.una.cw/cw_registry/ // Confirmed by registry 2013-03-26 @@ -895,16 +916,18 @@ org.do sld.do web.do -// dz : https://en.wikipedia.org/wiki/.dz +// dz : http://www.nic.dz/images/pdf_nic/charte.pdf dz +art.dz +asso.dz com.dz +edu.dz +gov.dz org.dz net.dz -gov.dz -edu.dz -asso.dz pol.dz -art.dz +soc.dz +tm.dz // ec : http://www.nic.ec/reg/paso1.asp // Submitted by registry @@ -1002,6 +1025,10 @@ pro.fj *.fk // fm : https://en.wikipedia.org/wiki/.fm +com.fm +edu.fm +net.fm +org.fm fm // fo : https://en.wikipedia.org/wiki/.fo @@ -1041,6 +1068,8 @@ ga gb // gd : https://en.wikipedia.org/wiki/.gd +edu.gd +gov.gd gd // ge : http://www.nic.net.ge/policy_en.pdf @@ -1132,7 +1161,7 @@ gov.gr // gs : https://en.wikipedia.org/wiki/.gs gs -// gt : http://www.gt/politicas_de_registro.html +// gt : https://www.gt/sitio/registration_policy.php?lang=en gt com.gt edu.gt @@ -1156,6 +1185,7 @@ org.gu web.gu // gw : https://en.wikipedia.org/wiki/.gw +// gw : https://nic.gw/regras/ gw // gy : https://en.wikipedia.org/wiki/.gy @@ -3785,7 +3815,7 @@ gov.lc // li : https://en.wikipedia.org/wiki/.li li -// lk : http://www.nic.lk/seclevpr.html +// lk : https://www.nic.lk/index.php/domain-registration/lk-domain-naming-structure lk gov.lk sch.lk @@ -4574,15 +4604,17 @@ gob.mx edu.mx net.mx -// my : http://www.mynic.net.my/ +// my : http://www.mynic.my/ +// Available strings: https://mynic.my/resources/domains/buying-a-domain/ my +biz.my com.my -net.my -org.my -gov.my edu.my +gov.my mil.my name.my +net.my +org.my // mz : http://www.uem.mz/ // Submitted by registry @@ -4679,13 +4711,13 @@ web.ni // ccTLD for the Netherlands nl -// no : http://www.norid.no/regelverk/index.en.html -// The Norwegian registry has declined to notify us of updates. The web pages -// referenced below are the official source of the data. There is also an -// announce mailing list: -// https://postlister.uninett.no/sympa/info/norid-diskusjon +// no : https://www.norid.no/en/om-domenenavn/regelverk-for-no/ +// Norid geographical second level domains : https://www.norid.no/en/om-domenenavn/regelverk-for-no/vedlegg-b/ +// Norid category second level domains : https://www.norid.no/en/om-domenenavn/regelverk-for-no/vedlegg-c/ +// Norid category second-level domains managed by parties other than Norid : https://www.norid.no/en/om-domenenavn/regelverk-for-no/vedlegg-d/ +// RSS feed: https://teknisk.norid.no/en/feed/ no -// Norid generic domains : http://www.norid.no/regelverk/vedlegg-c.en.html +// Norid category second level domains : https://www.norid.no/en/om-domenenavn/regelverk-for-no/vedlegg-c/ fhs.no vgs.no fylkesbibl.no @@ -4693,13 +4725,13 @@ folkebibl.no museum.no idrett.no priv.no -// Non-Norid generic domains : http://www.norid.no/regelverk/vedlegg-d.en.html +// Norid category second-level domains managed by parties other than Norid : https://www.norid.no/en/om-domenenavn/regelverk-for-no/vedlegg-d/ mil.no stat.no dep.no kommune.no herad.no -// no geographical names : http://www.norid.no/regelverk/vedlegg-b.en.html +// Norid geographical second level domains : https://www.norid.no/en/om-domenenavn/regelverk-for-no/vedlegg-b/ // counties aa.no ah.no @@ -5828,7 +5860,7 @@ com.ps org.ps net.ps -// pt : http://online.dns.pt/dns/start_dns +// pt : https://www.dns.pt/en/domain/pt-terms-and-conditions-registration-rules/ pt net.pt gov.pt @@ -6065,8 +6097,10 @@ biz.ss com.ss edu.ss gov.ss +me.ss net.ss org.ss +sch.ss // st : http://www.nic.st/html/policyrules/ st @@ -6075,7 +6109,6 @@ com.st consulado.st edu.st embaixada.st -gov.st mil.st net.st org.st @@ -6180,29 +6213,22 @@ gov.tm mil.tm edu.tm -// tn : https://en.wikipedia.org/wiki/.tn -// http://whois.ati.tn/ +// tn : http://www.registre.tn/fr/ +// https://whois.ati.tn/ tn com.tn ens.tn fin.tn gov.tn ind.tn +info.tn intl.tn +mincom.tn nat.tn net.tn org.tn -info.tn perso.tn tourism.tn -edunet.tn -rnrt.tn -rns.tn -rnu.tn -mincom.tn -agrinet.tn -defense.tn -turen.tn // to : https://en.wikipedia.org/wiki/.to // Submitted by registry @@ -6327,7 +6353,6 @@ cv.ua dn.ua dnepropetrovsk.ua dnipropetrovsk.ua -dominic.ua donetsk.ua dp.ua if.ua @@ -6693,9 +6718,10 @@ mil.vc edu.vc // ve : https://registro.nic.ve/ -// Submitted by registry +// Submitted by registry nic@nic.ve and nicve@conatel.gob.ve ve arts.ve +bib.ve co.ve com.ve e12.ve @@ -6707,7 +6733,9 @@ info.ve int.ve mil.ve net.ve +nom.ve org.ve +rar.ve rec.ve store.ve tec.ve @@ -6786,6 +6814,9 @@ yt // xn--90ae ("bg", Bulgarian) : BG бг +// xn--mgbcpq6gpa1a ("albahrain", Arabic) : BH +البحرين + // xn--90ais ("bel", Belarusian/Russian Cyrillic) : BY // Operated by .by registry бел @@ -6918,12 +6949,15 @@ yt // xn--80ao21a ("Kaz", Kazakh) : KZ қаз +// xn--q7ce6a ("Lao", Lao) : LA +ລາວ + // xn--fzc2c9e2c ("Lanka", Sinhalese-Sinhala) : LK -// http://nic.lk +// https://nic.lk ලංකා // xn--xkc2al3hye2a ("Ilangai", Tamil) : LK -// http://nic.lk +// https://nic.lk இலங்கை // xn--mgbc0a9azcg ("Morocco/al-Maghrib", Arabic) : MA @@ -7043,7 +7077,13 @@ yt xxx // ye : http://www.y.net.ye/services/domain_name.htm -*.ye +ye +com.ye +edu.ye +gov.ye +net.ye +mil.ye +org.ye // za : https://www.zadna.org.za/content/page/domain-information/ ac.za @@ -7092,7 +7132,7 @@ org.zw // newGTLDs -// List of new gTLDs imported from https://www.icann.org/resources/registries/gtlds/v2/gtlds.json on 2020-04-02T18:20:31Z +// List of new gTLDs imported from https://www.icann.org/resources/registries/gtlds/v2/gtlds.json on 2021-11-13T15:12:42Z // This list is auto-generated, don't edit it manually. // aaa : 2015-02-26 American Automobile Association, Inc. aaa @@ -7118,7 +7158,7 @@ abc // able : 2015-06-25 Able Inc. able -// abogado : 2014-04-24 Minds + Machines Group Limited +// abogado : 2014-04-24 Registry Services, LLC abogado // abudhabi : 2015-07-30 Abu Dhabi Systems and Information Centre @@ -7175,9 +7215,6 @@ agency // aig : 2014-12-18 American International Group, Inc. aig -// aigo : 2015-08-06 aigo Digital Technology Co,Ltd. -aigo - // airbus : 2015-07-30 Airbus S.A.S. airbus @@ -7241,7 +7278,7 @@ analytics // android : 2014-08-07 Charleston Road Registry Inc. android -// anquan : 2015-01-08 QIHOO 360 TECHNOLOGY CO. LTD. +// anquan : 2015-01-08 Beijing Qihu Keji Co., Ltd. anquan // anz : 2015-07-31 Australia and New Zealand Banking Group Limited @@ -7301,7 +7338,7 @@ audi // audible : 2015-06-25 Amazon Registry Services, Inc. audible -// audio : 2014-03-20 Uniregistry, Corp. +// audio : 2014-03-20 UNR Corp. audio // auspost : 2015-08-13 Australian Postal Corporation @@ -7310,19 +7347,19 @@ auspost // author : 2014-12-18 Amazon Registry Services, Inc. author -// auto : 2014-11-13 Cars Registry Limited +// auto : 2014-11-13 XYZ.COM LLC auto -// autos : 2014-01-09 DERAutos, LLC +// autos : 2014-01-09 XYZ.COM LLC autos // avianca : 2015-01-08 Avianca Holdings S.A. avianca -// aws : 2015-06-25 Amazon Registry Services, Inc. +// aws : 2015-06-25 AWS Registry LLC aws -// axa : 2013-12-19 AXA SA +// axa : 2013-12-19 AXA Group Operations SAS axa // azure : 2014-12-18 Microsoft Corporation @@ -7397,7 +7434,7 @@ beats // beauty : 2015-12-03 XYZ.COM LLC beauty -// beer : 2014-01-09 Minds + Machines Group Limited +// beer : 2014-01-09 Registry Services, LLC beer // bentley : 2014-12-18 Bentley Motors Limited @@ -7439,7 +7476,7 @@ bio // black : 2014-01-16 Afilias Limited black -// blackfriday : 2014-01-16 Uniregistry, Corp. +// blackfriday : 2014-01-16 UNR Corp. blackfriday // blockbuster : 2015-07-30 Dish DBS Corporation @@ -7463,7 +7500,7 @@ bmw // bnpparibas : 2014-05-29 BNP Paribas bnpparibas -// boats : 2014-12-04 DERBoats, LLC +// boats : 2014-12-04 XYZ.COM LLC boats // boehringer : 2015-07-09 Boehringer Ingelheim International GmbH @@ -7502,7 +7539,7 @@ bot // boutique : 2013-11-14 Binky Moon, LLC boutique -// box : 2015-11-12 .BOX INC. +// box : 2015-11-12 Intercap Registry Inc. box // bradesco : 2014-12-18 Banco Bradesco S.A. @@ -7514,7 +7551,7 @@ bridgestone // broadway : 2014-12-22 Celebrate Broadway, Inc. broadway -// broker : 2014-12-11 Dotbroker Registry Limited +// broker : 2014-12-11 Dog Beach, LLC broker // brother : 2015-01-29 Brother Industries, Ltd. @@ -7586,7 +7623,7 @@ capital // capitalone : 2015-08-06 Capital One Financial Corporation capitalone -// car : 2015-01-22 Cars Registry Limited +// car : 2015-01-22 XYZ.COM LLC car // caravan : 2013-12-12 Caravan International, Inc. @@ -7604,18 +7641,15 @@ career // careers : 2013-10-02 Binky Moon, LLC careers -// cars : 2014-11-13 Cars Registry Limited +// cars : 2014-11-13 XYZ.COM LLC cars -// casa : 2013-11-21 Minds + Machines Group Limited +// casa : 2013-11-21 Registry Services, LLC casa -// case : 2015-09-03 CNH Industrial N.V. +// case : 2015-09-03 Helium TLDs Ltd case -// caseih : 2015-09-03 CNH Industrial N.V. -caseih - // cash : 2014-03-06 Binky Moon, LLC cash @@ -7640,9 +7674,6 @@ cbre // cbs : 2015-08-06 CBS Domains Inc. cbs -// ceb : 2015-04-09 The Corporate Executive Board Company -ceb - // center : 2013-11-07 Binky Moon, LLC center @@ -7655,7 +7686,7 @@ cern // cfa : 2014-08-28 CFA Institute cfa -// cfd : 2014-12-11 DotCFD Registry Limited +// cfd : 2014-12-11 ShortDot SA cfd // chanel : 2015-04-09 Chanel International B.V. @@ -7679,7 +7710,7 @@ cheap // chintai : 2015-06-11 CHINTAI Corporation chintai -// christmas : 2013-11-21 Uniregistry, Corp. +// christmas : 2013-11-21 UNR Corp. christmas // chrome : 2014-07-24 Charleston Road Registry Inc. @@ -7718,7 +7749,7 @@ claims // cleaning : 2013-12-05 Binky Moon, LLC cleaning -// click : 2014-06-05 Uniregistry, Corp. +// click : 2014-06-05 UNR Corp. click // clinic : 2014-03-20 Binky Moon, LLC @@ -7733,7 +7764,7 @@ clothing // cloud : 2015-04-16 Aruba PEC S.p.A. cloud -// club : 2013-11-08 .CLUB DOMAINS, LLC +// club : 2013-11-08 Registry Services, LLC club // clubmed : 2015-06-25 Club Méditerranée S.A. @@ -7790,7 +7821,7 @@ contact // contractors : 2013-09-10 Binky Moon, LLC contractors -// cooking : 2013-11-21 Minds + Machines Group Limited +// cooking : 2013-11-21 Registry Services, LLC cooking // cookingchannel : 2015-07-02 Lifestyle Domain Holdings, Inc. @@ -7823,7 +7854,7 @@ credit // creditcard : 2014-03-20 Binky Moon, LLC creditcard -// creditunion : 2015-01-22 CUNA Performance Resources, LLC +// creditunion : 2015-01-22 DotCooperation LLC creditunion // cricket : 2014-10-09 dot Cricket Limited @@ -7880,7 +7911,7 @@ day // dclk : 2014-11-20 Charleston Road Registry Inc. dclk -// dds : 2015-05-07 Minds + Machines Group Limited +// dds : 2015-05-07 Registry Services, LLC dds // deal : 2015-06-25 Amazon Registry Services, Inc. @@ -7919,7 +7950,7 @@ dentist // desi : 2013-11-14 Desi Networks LLC desi -// design : 2014-11-07 Top Level Design, LLC +// design : 2014-11-07 Registry Services, LLC design // dev : 2014-10-16 Charleston Road Registry Inc. @@ -7931,7 +7962,7 @@ dhl // diamonds : 2013-09-22 Binky Moon, LLC diamonds -// diet : 2014-06-26 Uniregistry, Corp. +// diet : 2014-06-26 UNR Corp. diet // digital : 2014-03-06 Binky Moon, LLC @@ -7991,7 +8022,7 @@ duck // dunlop : 2015-07-02 The Goodyear Tire & Rubber Company dunlop -// dupont : 2015-06-25 E. I. du Pont de Nemours and Company +// dupont : 2015-06-25 DuPont Specialty Products USA, LLC dupont // durban : 2014-03-24 ZA Central Registry NPC trading as ZA Central Registry @@ -8054,9 +8085,6 @@ esq // estate : 2013-08-27 Binky Moon, LLC estate -// esurance : 2015-07-23 Esurance Insurance Company -esurance - // etisalat : 2015-09-03 Emirates Telecommunications Corporation (trading as Etisalat) etisalat @@ -8111,7 +8139,7 @@ farm // farmers : 2015-07-09 Farmers Insurance Exchange farmers -// fashion : 2014-07-03 Minds + Machines Group Limited +// fashion : 2014-07-03 Registry Services, LLC fashion // fast : 2014-12-18 Amazon Registry Services, Inc. @@ -8162,16 +8190,16 @@ firmdale // fish : 2013-12-12 Binky Moon, LLC fish -// fishing : 2013-11-21 Minds + Machines Group Limited +// fishing : 2013-11-21 Registry Services, LLC fishing -// fit : 2014-11-07 Minds + Machines Group Limited +// fit : 2014-11-07 Registry Services, LLC fit // fitness : 2014-03-06 Binky Moon, LLC fitness -// flickr : 2015-04-02 Yahoo! Domain Services Inc. +// flickr : 2015-04-02 Flickr, Inc. flickr // flights : 2013-12-05 Binky Moon, LLC @@ -8183,7 +8211,7 @@ flir // florist : 2013-11-07 Binky Moon, LLC florist -// flowers : 2014-10-09 Uniregistry, Corp. +// flowers : 2014-10-09 UNR Corp. flowers // fly : 2014-05-08 Charleston Road Registry Inc. @@ -8204,7 +8232,7 @@ football // ford : 2014-11-13 Ford Motor Company ford -// forex : 2014-12-11 Dotforex Registry Limited +// forex : 2014-12-11 Dog Beach, LLC forex // forsale : 2014-05-22 Dog Beach, LLC @@ -8243,10 +8271,7 @@ ftr // fujitsu : 2015-07-30 Fujitsu Limited fujitsu -// fujixerox : 2015-07-23 Xerox DNHC LLC -fujixerox - -// fun : 2016-01-14 DotSpace Inc. +// fun : 2016-01-14 Radix FZC fun // fund : 2014-03-20 Binky Moon, LLC @@ -8273,7 +8298,7 @@ gallo // gallup : 2015-02-19 Gallup, Inc. gallup -// game : 2015-05-28 Uniregistry, Corp. +// game : 2015-05-28 UNR Corp. game // games : 2015-05-28 Dog Beach, LLC @@ -8282,7 +8307,7 @@ games // gap : 2015-07-31 The Gap, Inc. gap -// garden : 2014-06-26 Minds + Machines Group Limited +// garden : 2014-06-26 Registry Services, LLC garden // gay : 2019-05-23 Top Level Design, LLC @@ -8411,7 +8436,7 @@ guge // guide : 2013-09-13 Binky Moon, LLC guide -// guitars : 2013-11-14 Uniregistry, Corp. +// guitars : 2013-11-14 UNR Corp. guitars // guru : 2013-08-27 Binky Moon, LLC @@ -8444,7 +8469,7 @@ health // healthcare : 2014-06-12 Binky Moon, LLC healthcare -// help : 2014-06-26 Uniregistry, Corp. +// help : 2014-06-26 UNR Corp. help // helsinki : 2015-02-05 City of Helsinki @@ -8459,7 +8484,7 @@ hermes // hgtv : 2015-07-02 Lifestyle Domain Holdings, Inc. hgtv -// hiphop : 2014-03-06 Uniregistry, Corp. +// hiphop : 2014-03-06 UNR Corp. hiphop // hisamitsu : 2015-07-16 Hisamitsu Pharmaceutical Co.,Inc. @@ -8468,7 +8493,7 @@ hisamitsu // hitachi : 2014-10-31 Hitachi, Ltd. hitachi -// hiv : 2014-03-13 Uniregistry, Corp. +// hiv : 2014-03-13 UNR Corp. hiv // hkt : 2015-05-14 PCCW-HKT DataCom Services Limited @@ -8489,7 +8514,7 @@ homedepot // homegoods : 2015-07-16 The TJX Companies, Inc. homegoods -// homes : 2014-01-09 DERHomes, LLC +// homes : 2014-01-09 XYZ.COM LLC homes // homesense : 2015-07-16 The TJX Companies, Inc. @@ -8498,16 +8523,16 @@ homesense // honda : 2014-12-18 Honda Motor Co., Ltd. honda -// horse : 2013-11-21 Minds + Machines Group Limited +// horse : 2013-11-21 Registry Services, LLC horse // hospital : 2016-10-20 Binky Moon, LLC hospital -// host : 2014-04-17 DotHost Inc. +// host : 2014-04-17 Radix FZC host -// hosting : 2014-05-29 Uniregistry, Corp. +// hosting : 2014-05-29 UNR Corp. hosting // hot : 2015-08-27 Amazon Registry Services, Inc. @@ -8597,9 +8622,6 @@ insurance // insure : 2014-03-20 Binky Moon, LLC insure -// intel : 2015-08-06 Intel Corporation -intel - // international : 2013-11-07 Binky Moon, LLC international @@ -8630,9 +8652,6 @@ itau // itv : 2015-07-09 ITV Services Limited itv -// iveco : 2015-09-03 CNH Industrial N.V. -iveco - // jaguar : 2014-11-13 Jaguar Land Rover Ltd jaguar @@ -8642,9 +8661,6 @@ java // jcb : 2014-11-20 JCB Co., Ltd. jcb -// jcp : 2015-04-23 JCP Media, Inc. -jcp - // jeep : 2015-07-30 FCA US LLC. jeep @@ -8681,7 +8697,7 @@ jpmorgan // jprs : 2014-09-18 Japan Registry Services Co., Ltd. jprs -// juegos : 2014-03-20 Uniregistry, Corp. +// juegos : 2014-03-20 UNR Corp. juegos // juniper : 2015-07-30 JUNIPER NETWORKS, INC. @@ -8708,6 +8724,9 @@ kfh // kia : 2015-07-09 KIA MOTORS CORPORATION kia +// kids : 2021-08-13 DotKids Foundation Limited +kids + // kim : 2013-09-23 Afilias Limited kim @@ -8786,13 +8805,13 @@ latino // latrobe : 2014-06-16 La Trobe University latrobe -// law : 2015-01-22 LW TLD Limited +// law : 2015-01-22 Registry Services, LLC law // lawyer : 2014-03-20 Dog Beach, LLC lawyer -// lds : 2014-03-20 IRI Domain Management, LLC ("Applicant") +// lds : 2014-03-20 IRI Domain Management, LLC lds // lease : 2014-03-06 Binky Moon, LLC @@ -8849,7 +8868,7 @@ lincoln // linde : 2014-12-04 Linde Aktiengesellschaft linde -// link : 2013-11-14 Uniregistry, Corp. +// link : 2013-11-14 UNR Corp. link // lipsy : 2015-06-25 Lipsy Ltd @@ -8867,7 +8886,7 @@ lixil // llc : 2017-12-14 Afilias Limited llc -// llp : 2019-08-26 Dot Registry LLC +// llp : 2019-08-26 UNR Corp. llp // loan : 2014-11-20 dot Loan Limited @@ -8885,7 +8904,7 @@ locus // loft : 2015-07-30 Annco, Inc. loft -// lol : 2015-01-30 Uniregistry, Corp. +// lol : 2015-01-30 UNR Corp. lol // london : 2013-11-14 Dot London Domains Limited @@ -8915,10 +8934,7 @@ ltda // lundbeck : 2015-08-06 H. Lundbeck A/S lundbeck -// lupin : 2014-11-07 LUPIN LIMITED -lupin - -// luxe : 2014-01-09 Minds + Machines Group Limited +// luxe : 2014-01-09 Registry Services, LLC luxe // luxury : 2013-10-17 Luxury Partners, LLC @@ -8957,7 +8973,7 @@ market // marketing : 2013-11-07 Binky Moon, LLC marketing -// markets : 2014-12-11 Dotmarkets Registry Limited +// markets : 2014-12-11 Dog Beach, LLC markets // marriott : 2014-10-09 Marriott Worldwide Corporation @@ -9005,9 +9021,6 @@ menu // merckmsd : 2016-07-14 MSD Registry Holdings, Inc. merckmsd -// metlife : 2015-05-07 MetLife Services and Solutions, LLC -metlife - // miami : 2013-12-19 Minds + Machines Group Limited miami @@ -9047,7 +9060,7 @@ moe // moi : 2014-12-18 Amazon Registry Services, Inc. moi -// mom : 2015-04-16 Uniregistry, Corp. +// mom : 2015-04-16 UNR Corp. mom // monash : 2013-09-30 Monash University @@ -9059,7 +9072,7 @@ money // monster : 2015-09-11 XYZ.COM LLC monster -// mormon : 2013-12-05 IRI Domain Management, LLC ("Applicant") +// mormon : 2013-12-05 IRI Domain Management, LLC mormon // mortgage : 2014-03-20 Dog Beach, LLC @@ -9071,7 +9084,7 @@ moscow // moto : 2015-06-04 Motorola Trademark Holdings, LLC moto -// motorcycles : 2014-01-09 DERMotorcycles, LLC +// motorcycles : 2014-01-09 XYZ.COM LLC motorcycles // mov : 2014-01-30 Charleston Road Registry Inc. @@ -9089,6 +9102,9 @@ mtn // mtr : 2015-03-12 MTR Corporation Limited mtr +// music : 2021-05-04 DotMusic Limited +music + // mutual : 2015-04-02 Northwestern Mutual MU TLD Registry, LLC mutual @@ -9098,9 +9114,6 @@ nab // nagoya : 2013-10-24 GMO Registry, Inc. nagoya -// nationwide : 2015-07-23 Nationwide Mutual Insurance Company -nationwide - // natura : 2015-03-12 NATURA COSMÉTICOS S.A. natura @@ -9122,15 +9135,12 @@ netflix // network : 2013-11-14 Binky Moon, LLC network -// neustar : 2013-12-05 Registry Services, LLC +// neustar : 2013-12-05 NeuStar, Inc. neustar // new : 2014-01-30 Charleston Road Registry Inc. new -// newholland : 2015-09-03 CNH Industrial N.V. -newholland - // news : 2014-12-18 Dog Beach, LLC news @@ -9176,7 +9186,7 @@ nokia // northwesternmutual : 2015-06-18 Northwestern Mutual Registry, LLC northwesternmutual -// norton : 2014-12-04 Symantec Corporation +// norton : 2014-12-04 NortonLifeLock Inc. norton // now : 2015-06-25 Amazon Registry Services, Inc. @@ -9203,7 +9213,7 @@ nyc // obi : 2014-09-25 OBI Group Holding SE & Co. KGaA obi -// observer : 2015-04-30 Top Level Spectrum, Inc. +// observer : 2015-04-30 Dog Beach, LLC observer // off : 2015-07-23 Johnson Shareholdings, Inc. @@ -9236,15 +9246,12 @@ one // ong : 2014-03-06 Public Interest Registry ong -// onl : 2013-09-16 I-Registry Ltd. +// onl : 2013-09-16 iRegistry GmbH onl -// online : 2015-01-15 DotOnline Inc. +// online : 2015-01-15 Radix FZC online -// onyourside : 2015-07-23 Nationwide Mutual Insurance Company -onyourside - // ooo : 2014-01-09 INFIBEAM AVENUES LIMITED ooo @@ -9323,7 +9330,7 @@ philips // phone : 2016-06-02 Dish DBS Corporation phone -// photo : 2013-11-14 Uniregistry, Corp. +// photo : 2013-11-14 UNR Corp. photo // photography : 2013-09-20 Binky Moon, LLC @@ -9335,7 +9342,7 @@ photos // physio : 2014-05-01 PhysBiz Pty Ltd physio -// pics : 2013-11-14 Uniregistry, Corp. +// pics : 2013-11-14 UNR Corp. pics // pictet : 2014-06-26 Pictet Europe S.A. @@ -9398,7 +9405,7 @@ pramerica // praxi : 2013-12-05 Praxi S.p.A. praxi -// press : 2014-04-03 DotPress Inc. +// press : 2014-04-03 Radix FZC press // prime : 2015-06-25 Amazon Registry Services, Inc. @@ -9422,7 +9429,7 @@ promo // properties : 2013-12-05 Binky Moon, LLC properties -// property : 2014-05-22 Uniregistry, Corp. +// property : 2014-05-22 UNR Corp. property // protection : 2015-04-23 XYZ.COM LLC @@ -9449,9 +9456,6 @@ quebec // quest : 2015-03-26 XYZ.COM LLC quest -// qvc : 2015-07-30 QVC, Inc. -qvc - // racing : 2014-12-04 Premier Registry Limited racing @@ -9470,7 +9474,7 @@ realestate // realtor : 2014-05-29 Real Estate Domains LLC realtor -// realty : 2015-03-19 Fegistry, LLC +// realty : 2015-03-19 Dog Beach, LLC realty // recipes : 2013-10-17 Binky Moon, LLC @@ -9533,7 +9537,7 @@ reviews // rexroth : 2015-06-18 Robert Bosch GMBH rexroth -// rich : 2013-11-21 I-Registry Ltd. +// rich : 2013-11-21 iRegistry GmbH rich // richardli : 2015-05-14 Pacific Century Asset Management (HK) Limited @@ -9542,9 +9546,6 @@ richardli // ricoh : 2014-11-20 Ricoh Company, Ltd. ricoh -// rightathome : 2015-07-23 Johnson Shareholdings, Inc. -rightathome - // ril : 2015-04-02 Reliance Industries Limited ril @@ -9554,16 +9555,13 @@ rio // rip : 2014-07-10 Dog Beach, LLC rip -// rmit : 2015-11-19 Royal Melbourne Institute of Technology -rmit - // rocher : 2014-12-18 Ferrero Trading Lux S.A. rocher // rocks : 2013-11-14 Dog Beach, LLC rocks -// rodeo : 2013-12-19 Minds + Machines Group Limited +// rodeo : 2013-12-19 Registry Services, LLC rodeo // rogers : 2015-08-06 Rogers Communications Canada Inc. @@ -9641,7 +9639,7 @@ saxo // sbi : 2015-03-12 STATE BANK OF INDIA sbi -// sbs : 2014-11-07 SPECIAL BROADCASTING SERVICE CORPORATION +// sbs : 2014-11-07 ShortDot SA sbs // sca : 2014-03-13 SVENSKA CELLULOSA AKTIEBOLAGET SCA (publ) @@ -9674,9 +9672,6 @@ science // scjohnson : 2015-07-23 Johnson Shareholdings, Inc. scjohnson -// scor : 2014-10-31 SCOR SE -scor - // scot : 2014-01-23 Dot Scot Registry Limited scot @@ -9716,7 +9711,7 @@ sew // sex : 2014-11-13 ICM Registry SX LLC sex -// sexy : 2013-09-11 Uniregistry, Corp. +// sexy : 2013-09-11 UNR Corp. sexy // sfr : 2015-08-13 Societe Francaise du Radiotelephone - SFR @@ -9749,7 +9744,7 @@ shop // shopping : 2016-03-31 Binky Moon, LLC shopping -// shouji : 2015-01-08 QIHOO 360 TECHNOLOGY CO. LTD. +// shouji : 2015-01-08 Beijing Qihu Keji Co., Ltd. shouji // show : 2015-03-05 Binky Moon, LLC @@ -9758,9 +9753,6 @@ show // showtime : 2015-08-06 CBS Domains Inc. showtime -// shriram : 2014-01-23 Shriram Capital Ltd. -shriram - // silk : 2015-06-25 Amazon Registry Services, Inc. silk @@ -9770,7 +9762,7 @@ sina // singles : 2013-08-27 Binky Moon, LLC singles -// site : 2015-01-15 DotSite Inc. +// site : 2015-01-15 Radix FZC site // ski : 2015-04-09 Afilias Limited @@ -9830,7 +9822,7 @@ soy // spa : 2019-09-19 Asia Spa and Wellness Promotion Council Limited spa -// space : 2014-04-03 DotSpace Inc. +// space : 2014-04-03 Radix FZC space // sport : 2017-11-16 Global Association of International Sports Federations (GAISF) @@ -9839,9 +9831,6 @@ sport // spot : 2015-02-26 Amazon Registry Services, Inc. spot -// spreadbetting : 2014-12-11 Dotspreadbetting Registry Limited -spreadbetting - // srl : 2015-05-07 InterNetX, Corp srl @@ -9872,7 +9861,7 @@ stockholm // storage : 2014-12-22 XYZ.COM LLC storage -// store : 2015-04-09 DotStore Inc. +// store : 2015-04-09 Radix FZC store // stream : 2016-01-08 dot Stream Limited @@ -9899,7 +9888,7 @@ supply // support : 2013-10-24 Binky Moon, LLC support -// surf : 2014-01-09 Minds + Machines Group Limited +// surf : 2014-01-09 Registry Services, LLC surf // surgery : 2014-03-20 Binky Moon, LLC @@ -9911,18 +9900,12 @@ suzuki // swatch : 2015-01-08 The Swatch Group Ltd swatch -// swiftcover : 2015-07-23 Swiftcover Insurance Services Limited -swiftcover - // swiss : 2014-10-16 Swiss Confederation swiss // sydney : 2014-09-18 State of New South Wales, Department of Premier and Cabinet sydney -// symantec : 2014-12-04 Symantec Corporation -symantec - // systems : 2013-11-07 Binky Moon, LLC systems @@ -9947,7 +9930,7 @@ tatamotors // tatar : 2014-04-24 Limited Liability Company "Coordination Center of Regional Domain of Tatarstan Republic" tatar -// tattoo : 2013-08-30 Uniregistry, Corp. +// tattoo : 2013-08-30 UNR Corp. tattoo // tax : 2014-03-20 Binky Moon, LLC @@ -9965,7 +9948,7 @@ tdk // team : 2015-03-05 Binky Moon, LLC team -// tech : 2015-01-30 Personals TLD Inc. +// tech : 2015-01-30 Radix FZC tech // technology : 2013-09-13 Binky Moon, LLC @@ -9992,7 +9975,7 @@ theatre // tiaa : 2015-07-23 Teachers Insurance and Annuity Association of America tiaa -// tickets : 2015-02-05 Accent Media Limited +// tickets : 2015-02-05 XYZ.COM LLC tickets // tienda : 2013-11-14 Binky Moon, LLC @@ -10058,7 +10041,7 @@ toys // trade : 2014-01-23 Elite Registry Limited trade -// trading : 2014-12-11 Dottrading Registry Limited +// trading : 2014-12-11 Dog Beach, LLC trading // training : 2013-11-07 Binky Moon, LLC @@ -10076,7 +10059,7 @@ travelers // travelersinsurance : 2015-03-26 Travelers TLD, LLC travelersinsurance -// trust : 2014-10-16 NCC Group Inc. +// trust : 2014-10-16 UNR Corp. trust // trv : 2015-03-26 Travelers TLD, LLC @@ -10109,7 +10092,7 @@ unicom // university : 2014-03-06 Binky Moon, LLC university -// uno : 2013-09-11 DotSite Inc. +// uno : 2013-09-11 Radix FZC uno // uol : 2014-05-01 UBN INTERNET LTDA. @@ -10160,7 +10143,7 @@ villas // vin : 2015-06-18 Binky Moon, LLC vin -// vip : 2015-01-22 Minds + Machines Group Limited +// vip : 2015-01-22 Registry Services, LLC vip // virgin : 2014-09-25 Virgin Enterprises Limited @@ -10181,7 +10164,7 @@ vivo // vlaanderen : 2014-02-06 DNS.be vzw vlaanderen -// vodka : 2013-12-19 Minds + Machines Group Limited +// vodka : 2013-12-19 Registry Services, LLC vodka // volkswagen : 2015-05-14 Volkswagen Group of America Inc. @@ -10223,7 +10206,7 @@ wanggou // watch : 2013-11-14 Binky Moon, LLC watch -// watches : 2014-12-22 Richemont DNS Inc. +// watches : 2014-12-22 Afilias Limited watches // weather : 2015-01-08 International Business Machines Corporation @@ -10238,13 +10221,10 @@ webcam // weber : 2015-06-04 Saint-Gobain Weber SA weber -// website : 2014-04-03 DotWebsite Inc. +// website : 2014-04-03 Radix FZC website -// wed : 2013-10-01 Atgron, Inc. -wed - -// wedding : 2014-04-24 Minds + Machines Group Limited +// wedding : 2014-04-24 Registry Services, LLC wedding // weibo : 2015-03-05 Sina Corporation @@ -10286,7 +10266,7 @@ wolterskluwer // woodside : 2015-07-09 Woodside Petroleum Limited woodside -// work : 2013-12-19 Minds + Machines Group Limited +// work : 2013-12-19 Registry Services, LLC work // works : 2013-11-14 Binky Moon, LLC @@ -10313,7 +10293,7 @@ xerox // xfinity : 2015-07-09 Comcast IP Holdings I, LLC xfinity -// xihuan : 2015-01-08 QIHOO 360 TECHNOLOGY CO. LTD. +// xihuan : 2015-01-08 Beijing Qihu Keji Co., Ltd. xihuan // xin : 2014-12-11 Elegant Leader Limited @@ -10337,9 +10317,6 @@ xin // xn--3ds443g : 2013-09-08 TLD REGISTRY LIMITED OY 在线 -// xn--3oq18vl8pn36a : 2015-07-02 Volkswagen (China) Investment Co., Ltd. -大众汽车 - // xn--3pxu8k : 2015-01-15 VeriSign Sarl 点看 @@ -10349,7 +10326,7 @@ xin // xn--45q11c : 2013-11-21 Zodiac Gemini Ltd 八卦 -// xn--4gbrim : 2013-10-04 Fans TLD Limited +// xn--4gbrim : 2013-10-04 Helium TLDs Ltd موقع // xn--55qw42g : 2013-11-08 China Organizational Name Administration Center @@ -10454,7 +10431,7 @@ xin // xn--fzys8d69uvgm : 2015-05-14 PCCW Enterprises Limited 電訊盈科 -// xn--g2xx48c : 2015-01-30 Minds + Machines Group Limited +// xn--g2xx48c : 2015-01-30 Nawang Heli(Xiamen) Network Service Co., LTD. 购物 // xn--gckr3f0f : 2015-02-26 Amazon Registry Services, Inc. @@ -10490,9 +10467,6 @@ xin // xn--kcrx77d1x4a : 2014-11-07 Koninklijke Philips N.V. 飞利浦 -// xn--kpu716f : 2014-12-22 Richemont DNS Inc. -手表 - // xn--kput3i : 2014-02-13 Beijing RITT-Net Technology Development Co., Ltd 手机 @@ -10547,9 +10521,6 @@ xin // xn--p1acf : 2013-12-12 Rusnames Limited рус -// xn--pbt977c : 2014-12-22 Richemont DNS Inc. -珠宝 - // xn--pssy2u : 2015-01-15 VeriSign Sarl 大拿 @@ -10607,10 +10578,10 @@ vermögensberatung // xyz : 2013-12-05 XYZ.COM LLC xyz -// yachts : 2014-01-09 DERYachts, LLC +// yachts : 2014-01-09 XYZ.COM LLC yachts -// yahoo : 2015-04-02 Yahoo! Domain Services Inc. +// yahoo : 2015-04-02 Oath Inc. yahoo // yamaxun : 2014-12-18 Amazon Registry Services, Inc. @@ -10622,7 +10593,7 @@ yandex // yodobashi : 2014-11-20 YODOBASHI CAMERA CO.,LTD. yodobashi -// yoga : 2014-05-29 Minds + Machines Group Limited +// yoga : 2014-05-29 Registry Services, LLC yoga // yokohama : 2013-12-12 GMO Registry, Inc. @@ -10634,7 +10605,7 @@ you // youtube : 2014-05-01 Charleston Road Registry Inc. youtube -// yun : 2015-01-08 QIHOO 360 TECHNOLOGY CO. LTD. +// yun : 2015-01-08 Beijing Qihu Keji Co., Ltd. yun // zappos : 2015-06-25 Amazon Registry Services, Inc. @@ -10666,11 +10637,25 @@ cc.ua inf.ua ltd.ua +// 611coin : https://611project.org/ +611.to + +// Aaron Marais' Gitlab pages: https://lab.aaronleem.co.za +// Submitted by Aaron Marais +graphox.us + +// accesso Technology Group, plc. : https://accesso.com/ +// Submitted by accesso Team +*.devcdnaccesso.com + // Adobe : https://www.adobe.com/ -// Submitted by Ian Boston +// Submitted by Ian Boston and Lars Trieloff adobeaemcloud.com -adobeaemcloud.net *.dev.adobeaemcloud.com +hlx.live +adobeaemcloud.net +hlx.page +hlx3.page // Agnat sp. z o.o. : https://domena.pl // Submitted by Przemyslaw Plewa @@ -10685,6 +10670,10 @@ barsy.ca *.compute.estate *.alces.network +// all-inkl.com : https://all-inkl.com +// Submitted by Werner Kaltofen +kasserver.com + // Altervista: https://www.altervista.org // Submitted by Carlo Cannas altervista.org @@ -10732,6 +10721,10 @@ us-west-2.elasticbeanstalk.com *.elb.amazonaws.com *.elb.amazonaws.com.cn +// Amazon Global Accelerator : https://aws.amazon.com/global-accelerator/ +// Submitted by Daniel Massaguer +awsglobalaccelerator.com + // Amazon S3 : https://aws.amazon.com/s3/ // Submitted by Luke Wells s3.amazonaws.com @@ -10789,10 +10782,6 @@ s3-website.eu-west-2.amazonaws.com s3-website.eu-west-3.amazonaws.com s3-website.us-east-2.amazonaws.com -// Amsterdam Wireless: https://www.amsterdamwireless.nl/ -// Submitted by Imre Jonk -amsw.nl - // Amune : https://amune.org/ // Submitted by Team Amune t3l3p0rt.net @@ -10802,6 +10791,19 @@ tele.amune.org // Submitted by Apigee Security Team apigee.io +// Apphud : https://apphud.com +// Submitted by Alexander Selivanov +siiites.com + +// Appspace : https://www.appspace.com +// Submitted by Appspace Security Team +appspacehosted.com +appspaceusercontent.com + +// Appudo UG (haftungsbeschränkt) : https://www.appudo.com +// Submitted by Alexander Hochbaum +appudo.net + // Aptible : https://www.aptible.com/ // Submitted by Thomas Orozco on-aptible.com @@ -10827,15 +10829,27 @@ sweetpepper.org // Submitted by Vincent Tseng myasustor.com +// Atlassian : https://atlassian.com +// Submitted by Sam Smyth +cdn.prod.atlassian-dev.net + // AVM : https://avm.de // Submitted by Andreas Weise myfritz.net +// AVStack Pte. Ltd. : https://avstack.io +// Submitted by Jasper Hugo +onavstack.net + // AW AdvisorWebsites.com Software Inc : https://advisorwebsites.com // Submitted by James Kennedy *.awdev.ca *.advisor.ws +// AZ.pl sp. z.o.o: https://az.pl +// Submited by Krzysztof Wolski +ecommerce-shop.pl + // b-data GmbH : https://www.b-data.io // Submitted by Olivier Benz b-data.io @@ -10848,9 +10862,17 @@ backplaneapp.io // Submitted by Petros Angelatos balena-devices.com +// University of Banja Luka : https://unibl.org +// Domains for Republic of Srpska administrative entity. +// Submitted by Marko Ivanovic +rs.ba + // Banzai Cloud -// Submitted by Gabor Kozma +// Submitted by Janos Matyas +*.banzai.cloud app.banzaicloud.io +*.backyards.banzaicloud.io + // BetaInABox // Submitted by Adrian @@ -10860,14 +10882,30 @@ betainabox.com // Submitted by Nathan O'Sullivan bnr.la +// Bitbucket : http://bitbucket.org +// Submitted by Andy Ortlieb +bitbucket.io + // Blackbaud, Inc. : https://www.blackbaud.com // Submitted by Paul Crowder blackbaudcdn.net +// Blatech : http://www.blatech.net +// Submitted by Luke Bratch +of.je + +// Blue Bite, LLC : https://bluebite.com +// Submitted by Joshua Weiss +bluebite.io + // Boomla : https://boomla.com // Submitted by Tibor Halter boomla.net +// Boutir : https://www.boutir.com +// Submitted by Eric Ng Ka Ka +boutir.com + // Boxfuse : https://boxfuse.com // Submitted by Axel Fontaine boxfuse.io @@ -10881,6 +10919,10 @@ square7.de bplaced.net square7.net +// Brendly : https://brendly.rs +// Submitted by Dusan Radovanovic +shop.brendly.rs + // BrowserSafetyMark // Submitted by Dave Tharp browsersafetymark.io @@ -10891,46 +10933,54 @@ uk0.bigv.io dh.bytemark.co.uk vm.bytemark.co.uk +// Caf.js Labs LLC : https://www.cafjs.com +// Submitted by Antonio Lain +cafjs.com + // callidomus : https://www.callidomus.com/ // Submitted by Marcus Popp mycd.eu // Carrd : https://carrd.co // Submitted by AJ +drr.ac +uwu.ai carrd.co crd.co -uwu.ai +ju.mp // CentralNic : http://www.centralnic.com/names/domains // Submitted by registry ae.org -ar.com br.com cn.com com.de com.se de.com eu.com -gb.com gb.net -hu.com hu.net jp.net jpn.com -kr.com mex.com -no.com -qc.com ru.com sa.com se.net uk.com uk.net us.com -uy.com za.bz za.com +// No longer operated by CentralNic, these entries should be adopted and/or removed by current operators +// Submitted by Gavin Brown +ar.com +hu.com +kr.com +no.com +qc.com +uy.com + // Africa.com Web Solutions Ltd : https://registry.africa.com // Submitted by Gavin Brown africa.com @@ -10942,6 +10992,7 @@ gr.com // Radix FZC : http://domains.in.net // Submitted by Gavin Brown in.net +web.in // US REGISTRY LLC : http://us.org // Submitted by Gavin Brown @@ -10951,6 +11002,16 @@ us.org // Submitted by Gavin Brown co.com +// Roar Domains LLC : https://roar.basketball/ +// Submitted by Gavin Brown +aus.basketball +nz.basketball + +// BRS Media : https://brsmedia.com/ +// Submitted by Gavin Brown +radio.am +radio.fm + // c.la : http://www.c.la/ c.la @@ -10958,31 +11019,31 @@ c.la // Submitted by B. Blechschmidt certmgr.org -// Citrix : https://citrix.com -// Submitted by Alex Stoddard -xenapponazure.com +// Cityhost LLC : https://cityhost.ua +// Submitted by Maksym Rivtin +cx.ua // Civilized Discourse Construction Kit, Inc. : https://www.discourse.org/ // Submitted by Rishabh Nambiar & Michael Brown discourse.group discourse.team -// ClearVox : http://www.clearvox.nl/ -// Submitted by Leon Rowland -virtueeldomein.nl - // Clever Cloud : https://www.clever-cloud.com/ // Submitted by Quentin Adam cleverapps.io // Clerk : https://www.clerk.dev -// Submitted by Colin Sidoti +// Submitted by Colin Sidoti +clerk.app +clerkstage.app *.lcl.dev +*.lclstage.dev *.stg.dev +*.stgstage.dev -// Clic2000 : https://clic2000.fr -// Submitted by Mathilde Blanchemanche -clic2000.net +// ClickRising : https://clickrising.com/ +// Submitted by Umut Gumeli +clickrising.net // Cloud66 : https://www.cloud66.com/ // Submitted by Khash Sajadi @@ -11004,11 +11065,12 @@ cloudcontrolled.com cloudcontrolapp.com // Cloudera, Inc. : https://www.cloudera.com/ -// Submitted by Philip Langdale -cloudera.site +// Submitted by Kedarnath Waikar +*.cloudera.site // Cloudflare, Inc. : https://www.cloudflare.com/ -// Submitted by Jake Riesterer +// Submitted by Cloudflare Team +pages.dev trycloudflare.com workers.dev @@ -11049,10 +11111,6 @@ cloudns.pro cloudns.pw cloudns.us -// Cloudeity Inc : https://cloudeity.com -// Submitted by Stefan Dimitrov -cloudeity.net - // CNPY : https://cnpy.gdn // Submitted by Angelo Gladding cnpy.gdn @@ -11116,6 +11174,12 @@ curv.dev cyon.link cyon.site +// Danger Science Group: https://dangerscience.com/ +// Submitted by Skylar MacDonald +fnwk.site +folionetwork.site +platform0.app + // Daplie, Inc : https://daplie.com // Submitted by AJ ONeal daplie.me @@ -11151,18 +11215,41 @@ dyndns.dappnode.io // Submitted by Paul Biggar builtwithdark.com +// DataDetect, LLC. : https://datadetect.com +// Submitted by Andrew Banchich +demo.datadetect.com +instance.datadetect.com + // Datawire, Inc : https://www.datawire.io // Submitted by Richard Li edgestack.me +// DDNS5 : https://ddns5.com +// Submitted by Cameron Elliott +ddns5.com + // Debian : https://www.debian.org/ // Submitted by Peter Palfrader / Debian Sysadmin Team debian.net +// Deno Land Inc : https://deno.com/ +// Submitted by Luca Casonato +deno.dev +deno-staging.dev + // deSEC : https://desec.io/ // Submitted by Peter Thomassen dedyn.io +// Diher Solutions : https://diher.solutions +// Submitted by Didi Hermawan +*.rss.my.id +*.diher.solutions + +// DNS Africa Ltd https://dns.business +// Submitted by Calvin Browne +jozi.biz + // DNShome : https://www.dnshome.de/ // Submitted by Norbert Auler dnshome.de @@ -11176,6 +11263,10 @@ shop.th // Submitted by Paul Fang drayddns.com +// DreamCommerce : https://shoper.pl/ +// Submitted by Konrad Kotarba +shoparena.pl + // DreamHost : http://www.dreamhost.com/ // Submitted by Andrew Farmer dreamhosters.com @@ -11193,6 +11284,13 @@ drud.us // Submitted by Richard Harper duckdns.org +// Bip : https://bip.sh +// Submitted by Joel Kennedy +bip.sh + +// bitbridge.net : Submitted by Craig Welch, abeliidev@gmail.com +bitbridge.net + // dy.fi : http://dy.fi/ // Submitted by Heikki Hannikainen dy.fi @@ -11496,6 +11594,14 @@ ddnss.org definima.net definima.io +// DigitalOcean App Platform : https://www.digitalocean.com/products/app-platform/ +// Submitted by Braxton Huggins +ondigitalocean.app + +// DigitalOcean Spaces : https://www.digitalocean.com/products/spaces/ +// Submitted by Robin H. Johnson +*.digitaloceanspaces.com + // dnstrace.pro : https://dnstrace.pro/ // Submitted by Chris Partridge bci.dnstrace.pro @@ -11528,6 +11634,16 @@ dynv6.net // Submitted by Vladimir Dudr e4.cz +// eero : https://eero.com/ +// Submitted by Yue Kang +eero.online +eero-stage.online + +// Elementor : Elementor Ltd. +// Submitted by Anton Barkan +elementor.cloud +elementor.cool + // En root‽ : https://en-root.org // Submitted by Emmanuel Raviart en-root.fr @@ -11535,17 +11651,13 @@ en-root.fr // Enalean SAS: https://www.enalean.com // Submitted by Thomas Cottier mytuleap.com +tuleap-partners.com // ECG Robotics, Inc: https://ecgrobotics.org // Submitted by onred.one staging.onred.one -// Enonic : http://enonic.com/ -// Submitted by Erik Kaareng-Sunde -enonic.io -customer.enonic.io - // EU.org https://eu.org/ // Submitted by Pierre Beyssac eu.org @@ -11605,6 +11717,10 @@ tr.eu.org uk.eu.org us.eu.org +// Eurobyte : https://eurobyte.ru +// Submitted by Evgeniy Subbotin +eurodir.ru + // Evennode : http://www.evennode.com/ // Submitted by Michal Kralik eu-1.evennode.com @@ -11715,6 +11831,7 @@ u.channelsdvr.net // Fastly Inc. : http://www.fastly.com/ // Submitted by Fastly Security +edgecompute.app fastly-terrarium.com fastlylb.net map.fastlylb.net @@ -11728,16 +11845,11 @@ global.ssl.fastly.net // FASTVPS EESTI OU : https://fastvps.ru/ // Submitted by Likhachev Vasiliy -fastpanel.direct fastvps-server.com -myfast.space +fastvps.host myfast.host fastvps.site -fastvps.host - -// Featherhead : https://featherhead.xyz/ -// Submitted by Simon Menke -fhapp.xyz +myfast.space // Fedora : https://fedoraproject.org/ // submitted by Patrick Uiterwijk @@ -11749,15 +11861,20 @@ app.os.stg.fedoraproject.org // FearWorks Media Ltd. : https://fearworksmedia.co.uk // submitted by Keith Fairley -conn.uk -copro.uk couk.me ukco.me +conn.uk +copro.uk +hosp.uk // Fermax : https://fermax.com/ // submitted by Koen Van Isterdael mydobiss.com +// FH Muenster : https://www.fh-muenster.de +// Submitted by Robin Naundorf +fh-muenster.io + // Filegear Inc. : https://www.filegear.com // Submitted by Jason Zhu filegear.me @@ -11772,10 +11889,47 @@ filegear-sg.me // Submitted by Chris Raynor firebaseapp.com +// Firewebkit : https://www.firewebkit.com +// Submitted by Majid Qureshi +fireweb.app + +// FLAP : https://www.flap.cloud +// Submitted by Louis Chemineau +flap.id + +// FlashDrive : https://flashdrive.io +// Submitted by Eric Chan +onflashdrive.app +fldrv.com + +// fly.io: https://fly.io +// Submitted by Kurt Mackey +fly.dev +edgeapp.net +shw.io + // Flynn : https://flynn.io // Submitted by Jonathan Rudenberg flynnhosting.net +// Forgerock : https://www.forgerock.com +// Submitted by Roderick Parr +forgeblocks.com +id.forgerock.io + +// Framer : https://www.framer.com +// Submitted by Koen Rouwhorst +framer.app +framercanvas.com + +// Frusky MEDIA&PR : https://www.frusky.de +// Submitted by Victor Pupynin +*.frusky.de + +// RavPage : https://www.ravpage.co.il +// Submitted by Roni Horowitz +ravpage.co.il + // Frederik Braun https://frederik-braun.com // Submitted by Frederik Braun 0e.vc @@ -11793,6 +11947,14 @@ freeboxos.fr // Submitted by Daniel Stone freedesktop.org +// freemyip.com : https://freemyip.com +// Submitted by Cadence +freemyip.com + +// FunkFeuer - Verein zur Förderung freier Netze : https://www.funkfeuer.at +// Submitted by Daniel A. Maierhofer +wien.funkfeuer.at + // Futureweb OG : http://www.futureweb.at // Submitted by Andreas Schnederle-Wagner *.futurecms.at @@ -11816,30 +11978,59 @@ usercontent.jp // Gentlent, Inc. : https://www.gentlent.com // Submitted by Tom Klein gentapps.com +gentlentapis.com lab.ms +cdn-edges.net + +// Ghost Foundation : https://ghost.org +// Submitted by Matt Hanley +ghost.io + +// GignoSystemJapan: http://gsj.bz +// Submitted by GignoSystemJapan +gsj.bz // GitHub, Inc. // Submitted by Patrick Toomey -github.io githubusercontent.com +githubpreview.dev +github.io // GitLab, Inc. // Submitted by Alex Hanselka gitlab.io +// Gitplac.si - https://gitplac.si +// Submitted by Aljaž Starc +gitapp.si +gitpage.si + // Glitch, Inc : https://glitch.com // Submitted by Mads Hartmann glitch.me +// Global NOG Alliance : https://nogalliance.org/ +// Submitted by Sander Steffann +nog.community + +// Globe Hosting SRL : https://www.globehosting.com/ +// Submitted by Gavin Brown +co.ro +shop.ro + // GMO Pepabo, Inc. : https://pepabo.com/ // Submitted by dojineko lolipop.io // GOV.UK Platform as a Service : https://www.cloud.service.gov.uk/ -// Submitted by Tom Whitwell +// Submitted by Tom Whitwell cloudapps.digital london.cloudapps.digital +// GOV.UK Pay : https://www.payments.service.gov.uk/ +// Submitted by Richard Baker +pymnt.uk + // UKHomeOffice : https://www.gov.uk/government/organisations/home-office // Submitted by Jon Shanks homeoffice.gov.uk @@ -11847,7 +12038,6 @@ homeoffice.gov.uk // GlobeHosting, Inc. // Submitted by Zoltan Egresi ro.im -shop.ro // GoIP DNS Services : http://www.goip.de // Submitted by Christian Poulter @@ -11861,6 +12051,18 @@ web.app *.0emm.com appspot.com *.r.appspot.com +codespot.com +googleapis.com +googlecode.com +pagespeedmobilizer.com +publishproxy.com +withgoogle.com +withyoutube.com +*.gateway.dev +cloud.goog +translate.goog +*.usercontent.goog +cloudfunctions.net blogspot.ae blogspot.al blogspot.am @@ -11935,24 +12137,20 @@ blogspot.td blogspot.tw blogspot.ug blogspot.vn -cloudfunctions.net -cloud.goog -codespot.com -googleapis.com -googlecode.com -pagespeedmobilizer.com -publishproxy.com -withgoogle.com -withyoutube.com -// Aaron Marais' Gitlab pages: https://lab.aaronleem.co.za -// Submitted by Aaron Marais -graphox.us +// Goupile : https://goupile.fr +// Submitted by Niels Martignene +goupile.fr // Group 53, LLC : https://www.group53.com // Submitted by Tyler Todd awsmppl.com +// GünstigBestellen : https://günstigbestellen.de +// Submitted by Furkan Akkoc +günstigbestellen.de +günstigliefern.de + // Hakaran group: http://hakaran.cz // Submited by Arseniy Sokolov fin.ci @@ -11974,6 +12172,10 @@ hashbang.sh hasura.app hasura-app.io +// Heilbronn University of Applied Sciences - Faculty Informatics (GitLab Pages): https://www.hs-heilbronn.de +// Submitted by Richard Zowalla +pages.it.hs-heilbronn.de + // Hepforge : https://www.hepforge.org // Submitted by David Grellscheid hepforge.org @@ -11991,20 +12193,29 @@ ravendb.me development.run ravendb.run +// home.pl S.A.: https://home.pl +// Submited by Krzysztof Wolski +homesklep.pl + +// Hong Kong Productivity Council: https://www.hkpc.org/ +// Submitted by SECaaS Team +secaas.hk + // HOSTBIP REGISTRY : https://www.hostbip.com/ // Submitted by Atanunu Igbunuroghene -bpl.biz orx.biz -ng.city biz.gl -ng.ink col.ng firm.ng gen.ng ltd.ng ngo.ng -ng.school +edu.scot sch.so +org.yt + +// HostyHosting (hostyhosting.com) +hostyhosting.io // Häkkinen.fi // Submitted by Eero Häkkinen @@ -12019,6 +12230,19 @@ moonscale.net // Submitted by Hannu Aronsson iki.fi +// Impertrix Solutions : +// Submitted by Zhixiang Zhao +impertrixcdn.com +impertrix.com + +// Incsub, LLC: https://incsub.com/ +// Submitted by Aaron Edwards +smushcdn.com +wphostedmail.com +wpmucdn.com +tempurl.host +wpmudev.host + // Individual Network Berlin e.V. : https://www.in-berlin.de/ // Submitted by Christian Seitz dyn-berlin.de @@ -12074,6 +12298,14 @@ to.leg.br // Submitted by Wolfgang Schwarz pixolino.com +// Internet-Pro, LLP: https://netangels.ru/ +// Submited by Vasiliy Sheredeko +na4u.ru + +// iopsys software solutions AB : https://iopsys.eu/ +// Submitted by Roman Azarenko +iopsys.se + // IPiFony Systems, Inc. : https://www.ipifony.com/ // Submitted by Matthew Hardeman ipifony.net @@ -12089,6 +12321,92 @@ iserv.dev // Submitted by Yuji Minagawa iobb.net +// Jelastic, Inc. : https://jelastic.com/ +// Submited by Ihor Kolodyuk +mel.cloudlets.com.au +cloud.interhostsolutions.be +users.scale.virtualcloud.com.br +mycloud.by +alp1.ae.flow.ch +appengine.flow.ch +es-1.axarnet.cloud +diadem.cloud +vip.jelastic.cloud +jele.cloud +it1.eur.aruba.jenv-aruba.cloud +it1.jenv-aruba.cloud +keliweb.cloud +cs.keliweb.cloud +oxa.cloud +tn.oxa.cloud +uk.oxa.cloud +primetel.cloud +uk.primetel.cloud +ca.reclaim.cloud +uk.reclaim.cloud +us.reclaim.cloud +ch.trendhosting.cloud +de.trendhosting.cloud +jele.club +amscompute.com +clicketcloud.com +dopaas.com +hidora.com +paas.hosted-by-previder.com +rag-cloud.hosteur.com +rag-cloud-ch.hosteur.com +jcloud.ik-server.com +jcloud-ver-jpc.ik-server.com +demo.jelastic.com +kilatiron.com +paas.massivegrid.com +jed.wafaicloud.com +lon.wafaicloud.com +ryd.wafaicloud.com +j.scaleforce.com.cy +jelastic.dogado.eu +fi.cloudplatform.fi +demo.datacenter.fi +paas.datacenter.fi +jele.host +mircloud.host +paas.beebyte.io +sekd1.beebyteapp.io +jele.io +cloud-fr1.unispace.io +jc.neen.it +cloud.jelastic.open.tim.it +jcloud.kz +upaas.kazteleport.kz +cloudjiffy.net +fra1-de.cloudjiffy.net +west1-us.cloudjiffy.net +jls-sto1.elastx.net +jls-sto2.elastx.net +jls-sto3.elastx.net +faststacks.net +fr-1.paas.massivegrid.net +lon-1.paas.massivegrid.net +lon-2.paas.massivegrid.net +ny-1.paas.massivegrid.net +ny-2.paas.massivegrid.net +sg-1.paas.massivegrid.net +jelastic.saveincloud.net +nordeste-idc.saveincloud.net +j.scaleforce.net +jelastic.tsukaeru.net +sdscloud.pl +unicloud.pl +mircloud.ru +jelastic.regruhosting.ru +enscaled.sg +jele.site +jelastic.team +orangecloud.tn +j.layershift.co.uk +phx.enscaled.us +mircloud.us + // Jino : https://www.jino.ru // Submitted by Sergey Ulyashin myjino.ru @@ -12097,6 +12415,10 @@ myjino.ru *.spectrum.myjino.ru *.vps.myjino.ru +// Jotelulu S.L. : https://jotelulu.com +// Submitted by Daniel Fariña +jotelulu.cloud + // Joyent : https://www.joyent.com/ // Submitted by Brian Bennett *.triton.zone @@ -12128,10 +12450,20 @@ knightpoint.systems // Submitted by DisposaBoy oya.to +// Katholieke Universiteit Leuven: https://www.kuleuven.be +// Submitted by Abuse KU Leuven +kuleuven.cloud +ezproxy.kuleuven.be + // .KRD : http://nic.krd/data/krd/Registration%20Policy.pdf co.krd edu.krd +// Krellian Ltd. : https://krellian.com +// Submitted by Ben Francis +krellian.net +webthings.io + // LCube - Professional hosting e.K. : https://www.lcube-webhosting.de // Submitted by Lars Laehn git-repos.de @@ -12162,10 +12494,6 @@ co.technology // Submitted by Greg Holland app.lmpm.com -// Linki Tools UG : https://linki.tools -// Submitted by Paulo Matos -linkitools.space - // linkyard ldt: https://www.linkyard.ch/ // Submitted by Mario Siegenthaler linkyard.cloud @@ -12174,12 +12502,18 @@ linkyard-cloud.ch // Linode : https://linode.com // Submitted by members.linode.com -nodebalancer.linode.com +*.nodebalancer.linode.com +*.linodeobjects.com +ip.linodeusercontent.com // LiquidNet Ltd : http://www.liquidnetlimited.com/ // Submitted by Victor Velchev we.bs +// localzone.xyz +// Submitted by Kenny Niehage +localzone.xyz + // Log'in Line : https://www.loginline.com/ // Submitted by Rémi Mach loginline.app @@ -12188,6 +12522,14 @@ loginline.io loginline.services loginline.site +// Lokalized : https://lokalized.nl +// Submitted by Noah Taheij +servers.run + +// Lõhmus Family, The +// Submitted by Heiki Lõhmus +lohmus.me + // LubMAN UMCS Sp. z o.o : https://lubman.pl/ // Submitted by Ireneusz Maliszewski krasnik.pl @@ -12199,7 +12541,6 @@ swidnik.pl // Lug.org.uk : https://lug.org.uk // Submitted by Jon Spriggs -uklugs.org glug.org.uk lug.org.uk lugs.org.uk @@ -12225,6 +12566,7 @@ barsy.online barsy.org barsy.pro barsy.pub +barsy.ro barsy.shop barsy.site barsy.support @@ -12243,6 +12585,34 @@ mayfirst.org // Submitted by Ilya Zaretskiy hb.cldmail.ru +// Mail Transfer Platform : https://www.neupeer.com +// Submitted by Li Hui +cn.vu + +// Maze Play: https://www.mazeplay.com +// Submitted by Adam Humpherys +mazeplay.com + +// mcpe.me : https://mcpe.me +// Submitted by Noa Heyl +mcpe.me + +// McHost : https://mchost.ru +// Submitted by Evgeniy Subbotin +mcdir.me +mcdir.ru +mcpre.ru +vps.mcdir.ru + +// Mediatech : https://mediatech.by +// Submitted by Evgeniy Kozhuhovskiy +mediatech.by +mediatech.dev + +// Medicom Health : https://medicomhealth.com +// Submitted by Michael Olson +hra.health + // Memset hosting : https://www.memset.com // Submitted by Tom Whitwell miniserver.com @@ -12250,7 +12620,7 @@ memset.net // MetaCentrum, CESNET z.s.p.o. : https://www.metacentrum.cz/en/ // Submitted by Zdeněk Šustr -cloud.metacentrum.cz +*.cloud.metacentrum.cz custom.metacentrum.cz // MetaCentrum, CESNET z.s.p.o. : https://www.metacentrum.cz/en/ @@ -12267,11 +12637,29 @@ eu.meteorapp.com co.pl // Microsoft Corporation : http://microsoft.com -// Submitted by Mostafa Elzeiny +// Submitted by Mitch Webster *.azurecontainer.io azurewebsites.net azure-mobile.net cloudapp.net +azurestaticapps.net +centralus.azurestaticapps.net +eastasia.azurestaticapps.net +eastus2.azurestaticapps.net +westeurope.azurestaticapps.net +westus2.azurestaticapps.net + +// minion.systems : http://minion.systems +// Submitted by Robert Böttinger +csx.cc + +// Mintere : https://mintere.com/ +// Submitted by Ben Aubin +mintere.site + +// MobileEducation, LLC : https://joinforte.com +// Submitted by Grayson Martin +forte.id // Mozilla Corporation : https://mozilla.com // Submitted by Ben Francis @@ -12287,35 +12675,48 @@ net.ru org.ru pp.ru +// Mythic Beasts : https://www.mythic-beasts.com +// Submitted by Paul Cammish +hostedpi.com +customer.mythic-beasts.com +caracal.mythic-beasts.com +fentiger.mythic-beasts.com +lynx.mythic-beasts.com +ocelot.mythic-beasts.com +oncilla.mythic-beasts.com +onza.mythic-beasts.com +sphinx.mythic-beasts.com +vs.mythic-beasts.com +x.mythic-beasts.com +yali.mythic-beasts.com +cust.retrosnub.co.uk + // Nabu Casa : https://www.nabucasa.com // Submitted by Paulus Schoutsen ui.nabu.casa // Names.of.London : https://names.of.london/ -// Submitted by James Stevens or +// Submitted by James Stevens or pony.club of.fashion -on.fashion -of.football in.london of.london +from.marketing +with.marketing for.men +repair.men and.mom for.mom for.one +under.one for.sale -of.work +that.win +from.work to.work -// NCTU.ME : https://nctu.me/ -// Submitted by Tocknicsu -nctu.me - // Netlify : https://www.netlify.com // Submitted by Jessica Parsons -bitballoon.com netlify.app -netlify.com // Neustar Inc. // Submitted by Trung Tran @@ -12333,6 +12734,20 @@ nh-serv.co.uk // Submitted by Jeff Wheelhouse nfshost.com +// Noop : https://noop.app +// Submitted by Nathaniel Schweinberg +*.developer.app +noop.app + +// Northflank Ltd. : https://northflank.com/ +// Submitted by Marco Suter +*.northflank.app +*.code.run + +// Noticeable : https://noticeable.io +// Submitted by Laurent Pellegrino +noticeable.news + // Now-DNS : https://now-dns.com // Submitted by Steve Russell dnsking.ch @@ -12471,60 +12886,6 @@ pcloud.host // Submitted by Matthew Brown nyc.mn -// NymNom : https://nymnom.com/ -// Submitted by NymNom -nom.ae -nom.af -nom.ai -nom.al -nym.by -nom.bz -nym.bz -nom.cl -nym.ec -nom.gd -nom.ge -nom.gl -nym.gr -nom.gt -nym.gy -nym.hk -nom.hn -nym.ie -nom.im -nom.ke -nym.kz -nym.la -nym.lc -nom.li -nym.li -nym.lt -nym.lu -nom.lv -nym.me -nom.mk -nym.mn -nym.mx -nom.nu -nym.nz -nym.pe -nym.pt -nom.pw -nom.qa -nym.ro -nom.rs -nom.si -nym.sk -nom.st -nym.su -nym.sx -nom.tj -nym.tw -nom.ug -nom.uy -nom.vc -nom.vg - // Observable, Inc. : https://observablehq.com // Submitted by Mike Bostock static.observableusercontent.com @@ -12533,35 +12894,66 @@ static.observableusercontent.com // Submitted by Andrew Sampson cya.gg +// OMG.LOL : +// Submitted by Adam Newbold +omg.lol + // Omnibond Systems, LLC. : https://www.omnibond.com // Submitted by Cole Estep cloudycluster.net +// OmniWe Limited: https://omniwe.com +// Submitted by Vicary Archangel +omniwe.site + +// One.com: https://www.one.com/ +// Submitted by Jacob Bunk Nielsen +service.one + // One Fold Media : http://www.onefoldmedia.com/ // Submitted by Eddie Jones nid.io +// Open Social : https://www.getopensocial.com/ +// Submitted by Alexander Varwijk +opensocial.site + // OpenCraft GmbH : http://opencraft.com/ // Submitted by Sven Marnach opencraft.hosting +// OpenResearch GmbH: https://openresearch.com/ +// Submitted by Philipp Schmid +orsites.com + // Opera Software, A.S.A. // Submitted by Yngve Pettersen operaunite.com -// Oursky Limited : https://skygear.io/ -// Submited by Skygear Developer +// Oursky Limited : https://authgear.com/, https://skygear.io/ +// Submited by Authgear Team , Skygear Developer +authgear-staging.com +authgearapps.com skygearapp.com // OutSystems // Submitted by Duarte Santos outsystemscloud.com +// OVHcloud: https://ovhcloud.com +// Submitted by Vincent Cassé +*.webpaas.ovh.net +*.hosting.ovh.net + // OwnProvider GmbH: http://www.ownprovider.com // Submitted by Jan Moennich ownprovider.com own.pm +// OwO : https://whats-th.is/ +// Submitted by Dean Sheather +*.owo.codes + // OX : http://www.ox.rs // Submitted by Adam Grand ox.rs @@ -12578,6 +12970,21 @@ pgfog.com // Submitted by Jason Kriss pagefrontapp.com +// PageXL : https://pagexl.com +// Submitted by Yann Guichard +pagexl.com + +// Paywhirl, Inc : https://paywhirl.com/ +// Submitted by Daniel Netzer +*.paywhirl.com + +// pcarrier.ca Software Inc: https://pcarrier.ca/ +// Submitted by Pierre Carrier +bar0.net +bar1.net +bar2.net +rdv.to + // .pl domains (grandfathered) art.pl gliwice.pl @@ -12599,14 +13006,22 @@ mypep.link // Submitted by Kenneth Van Alstyne perspecta.cloud +// PE Ulyanov Kirill Sergeevich : https://airy.host +// Submitted by Kirill Ulyanov +lk3.ru + // Planet-Work : https://www.planet-work.com/ // Submitted by Frédéric VANNIÈRE on-web.fr // Platform.sh : https://platform.sh // Submitted by Nikola Kotur -*.platform.sh +bc.platform.sh +ent.platform.sh +eu.platform.sh +us.platform.sh *.platformsh.site +*.tst.site // Platter: https://platter.dev // Submitted by Patrick Flor @@ -12614,6 +13029,12 @@ platter-app.com platter-app.dev platterp.us +// Plesk : https://www.plesk.com/ +// Submitted by Anton Akhtyamov +pdns.page +plesk.page +pleskns.com + // Port53 : https://port53.io/ // Submitted by Maximilian Schieder dyn53.io @@ -12622,6 +13043,17 @@ dyn53.io // Submitted by Zulfais co.bn +// Postman, Inc : https://postman.com +// Submitted by Rahul Dhawan +postman-echo.com +pstmn.io +mock.pstmn.io +httpbin.org + +//prequalifyme.today : https://prequalifyme.today +//Submitted by DeepakTiwari deepak@ivylead.io +prequalifyme.today + // prgmr.com : https://prgmr.com/ // Submitted by Sarah Newman xen.prgmr.com @@ -12651,6 +13083,15 @@ byen.site // Submitted by Kor Nielsen pubtls.org +// PythonAnywhere LLP: https://www.pythonanywhere.com +// Submitted by Giles Thomas +pythonanywhere.com +eu.pythonanywhere.com + +// QOTO, Org. +// Submitted by Jeffrey Phillips Freeman +qoto.io + // Qualifio : https://qualifio.com/ // Submitted by Xavier De Cock qualifioapp.com @@ -12659,6 +13100,14 @@ qualifioapp.com // Submitted by Dani Biro qbuser.com +// Rad Web Hosting: https://radwebhosting.com +// Submitted by Scott Claeys +cloudsite.builders + +// Redgate Software: https://red-gate.com +// Submitted by Andrew Farries +instances.spawn.cc + // Redstar Consultants : https://www.redstarconsultants.com/ // Submitted by Jons Slemmer instantcloud.cn @@ -12696,6 +13145,10 @@ vaporcloud.io rackmaze.com rackmaze.net +// Rakuten Games, Inc : https://dev.viberplay.io +// Submitted by Joshua Zhang +g.vbrplsbx.io + // Rancher Labs, Inc : https://rancher.com // Submitted by Vincent Fiduccia *.on-k3s.io @@ -12718,6 +13171,7 @@ onrender.com // Repl.it : https://repl.it // Submitted by Mason Clayton repl.co +id.repl.co repl.run // Resin.io : https://resin.io @@ -12732,13 +13186,33 @@ hzc.io // Revitalised Limited : http://www.revitalised.co.uk // Submitted by Jack Price wellbeingzone.eu -ptplus.fit wellbeingzone.co.uk +// Rico Developments Limited : https://adimo.co +// Submitted by Colin Brown +adimo.co.uk + +// Riseup Networks : https://riseup.net +// Submitted by Micah Anderson +itcouldbewor.se + // Rochester Institute of Technology : http://www.rit.edu/ // Submitted by Jennifer Herting git-pages.rit.edu +// Rusnames Limited: http://rusnames.ru/ +// Submitted by Sergey Zotov +биз.рус +ком.рус +крым.рус +мир.рус +мск.рус +орг.рус +самара.рус +сочи.рус +спб.рус +я.рус + // Sandstorm Development Group, Inc. : https://sandcats.io/ // Submitted by Asheesh Laroia sandcats.io @@ -12755,6 +13229,7 @@ schokokeks.net // Scottish Government: https://www.gov.scot // Submitted by Martin Ellis gov.scot +service.gov.scot // Scry Security : http://www.scrysec.com // Submitted by Shante Adam @@ -12773,16 +13248,37 @@ my-firewall.org myfirewall.org spdns.org +// Seidat : https://www.seidat.com +// Submitted by Artem Kondratev +seidat.net + +// Sellfy : https://sellfy.com +// Submitted by Yuriy Romadin +sellfy.store + // Senseering GmbH : https://www.senseering.de // Submitted by Felix Mönckemeyer senseering.net +// Sendmsg: https://www.sendmsg.co.il +// Submitted by Assaf Stern +minisite.ms + +// Service Magnet : https://myservicemagnet.com +// Submitted by Dave Sanders +magnet.page + // Service Online LLC : http://drs.ua/ // Submitted by Serhii Bulakh biz.ua co.ua pp.ua +// Shift Crypto AG : https://shiftcrypto.ch +// Submitted by alex +shiftcrypto.dev +shiftcrypto.io + // ShiftEdit : https://shiftedit.net/ // Submitted by Adam Jimenez shiftedit.io @@ -12791,6 +13287,10 @@ shiftedit.io // Submitted by Alex Bowers myshopblocks.com +// Shopify : https://www.shopify.com +// Submitted by Alex Richter +myshopify.com + // Shopit : https://www.shopitcommerce.com/ // Submitted by Craig McMahon shopitsite.com @@ -12821,16 +13321,47 @@ bounty-full.com alpha.bounty-full.com beta.bounty-full.com +// Small Technology Foundation : https://small-tech.org +// Submitted by Aral Balkan +small-web.org + +// Smoove.io : https://www.smoove.io/ +// Submitted by Dan Kozak +vp4.me + +// Snowplow Analytics : https://snowplowanalytics.com/ +// Submitted by Ian Streeter +try-snowplow.com + +// SourceHut : https://sourcehut.org +// Submitted by Drew DeVault +srht.site + // Stackhero : https://www.stackhero.io // Submitted by Adrien Gillon stackhero-network.com +// Staclar : https://staclar.com +// Submitted by Matthias Merkel +novecore.site + // staticland : https://static.land // Submitted by Seth Vincent static.land dev.static.land sites.static.land +// Storebase : https://www.storebase.io +// Submitted by Tony Schirmer +storebase.store + +// Strategic System Consulting (eApps Hosting): https://www.eapps.com/ +// Submitted by Alex Oancea +vps-host.net +atl.jelastic.vps-host.net +njs.jelastic.vps-host.net +ric.jelastic.vps-host.net + // Sony Interactive Entertainment LLC : https://sie.com/ // Submitted by David Coles playstation-cloud.com @@ -12848,6 +13379,28 @@ spacekit.io // Submitted by Stefan Neufeind customer.speedpartner.de +// Spreadshop (sprd.net AG) : https://www.spreadshop.com/ +// Submitted by Martin Breest +myspreadshop.at +myspreadshop.com.au +myspreadshop.be +myspreadshop.ca +myspreadshop.ch +myspreadshop.com +myspreadshop.de +myspreadshop.dk +myspreadshop.es +myspreadshop.fi +myspreadshop.fr +myspreadshop.ie +myspreadshop.it +myspreadshop.net +myspreadshop.nl +myspreadshop.no +myspreadshop.pl +myspreadshop.se +myspreadshop.co.uk + // Standard Library : https://stdlib.com // Submitted by Jacob Lee api.stdlib.com @@ -12869,10 +13422,12 @@ user.srcf.net // Submitted by Dan Miller temp-dns.com -// Swisscom Application Cloud: https://developer.swisscom.com -// Submitted by Matthias.Winzeler -applicationcloud.io -scapp.io +// Supabase : https://supabase.io +// Submitted by Inian Parameshwaran +supabase.co +supabase.in +supabase.net +su.paba.se // Symfony, SAS : https://symfony.com/ // Submitted by Fabien Potencier @@ -12901,10 +13456,19 @@ synology.me vpnplus.to direct.quickconnect.to +// Tabit Technologies Ltd. : https://tabit.cloud/ +// Submitted by Oren Agiv +tabitorder.co.il + // TAIFUN Software AG : http://taifun-software.de // Submitted by Bjoern Henke taifun-dns.de +// Tailscale Inc. : https://www.tailscale.com +// Submitted by David Anderson +beta.tailscale.net +ts.net + // TASK geographical domains (www.task.gda.pl/uslugi/dns) gda.pl gdansk.pl @@ -12928,22 +13492,42 @@ gwiddle.co.uk // Thingdust AG : https://thingdust.com/ // Submitted by Adrian Imboden +*.firenet.ch +*.svc.firenet.ch +reservd.com thingdustdata.com cust.dev.thingdust.io cust.disrec.thingdust.io cust.prod.thingdust.io cust.testing.thingdust.io +reservd.dev.thingdust.io +reservd.disrec.thingdust.io +reservd.testing.thingdust.io + +// ticket i/O GmbH : https://ticket.io +// Submitted by Christian Franke +tickets.io // Tlon.io : https://tlon.io // Submitted by Mark Staarink arvo.network azimuth.network +tlon.network + +// Tor Project, Inc. : https://torproject.org +// Submitted by Antoine Beaupré bloxcms.com townnews-staging.com +// TradableBits: https://tradablebits.com +// Submitted by Dmitry Khrisanov dmitry@tradablebits.com +tbits.me + // TrafficPlex GmbH : https://www.trafficplex.de/ // Submitted by Phillipp Röll 12hp.at @@ -13009,6 +13593,10 @@ inc.hk virtualuser.de virtual-user.de +// Upli : https://upli.io +// Submitted by Lenny Bakkalian +upli.io + // urown.net : https://urown.net // Submitted by Hostmaster urown.cloud @@ -13022,6 +13610,12 @@ lib.de.us // Submitted by Danko Aleksejevs 2038.io +// Vercel, Inc : https://vercel.com/ +// Submitted by Connor Davis +vercel.app +vercel.dev +now.sh + // Viprinet Europe GmbH : http://www.viprinet.com // Submitted by Simon Kissel router.management @@ -13034,6 +13628,48 @@ v-info.info // Submitted by Nathan van Bakel voorloper.cloud +// Voxel.sh DNS : https://voxel.sh/dns/ +// Submitted by Mia Rehlinger +neko.am +nyaa.am +be.ax +cat.ax +es.ax +eu.ax +gg.ax +mc.ax +us.ax +xy.ax +nl.ci +xx.gl +app.gp +blog.gt +de.gt +to.gt +be.gy +cc.hn +blog.kg +io.kg +jp.kg +tv.kg +uk.kg +us.kg +de.ls +at.md +de.md +jp.md +to.md +indie.porn +vxl.sh +ch.tc +me.tc +we.tc +nyan.to +at.vg +blog.vu +dev.vu +me.vu + // V.UA Domain Administrator : https://domain.v.ua/ // Submitted by Serhii Rostilo v.ua @@ -13042,10 +13678,26 @@ v.ua // Submitted by Masayuki Note wafflecell.com +// WapBlog.ID : https://www.wapblog.id +// Submitted by Fajar Sodik +idnblogger.com +indowapblog.com +bloger.id +wblog.id +wbq.me +fastblog.net + // WebHare bv: https://www.webhare.com/ // Submitted by Arnold Hendriks *.webhare.dev +// WebHotelier Technologies Ltd: https://www.webhotelier.net/ +// Submitted by Apostolos Tsakpinis +reserve-online.net +reserve-online.com +bookonline.app +hotelwithflight.com + // WeDeploy by Liferay, Inc. : https://www.wedeploy.com // Submitted by Henrique Vicente wedeploy.io @@ -13056,6 +13708,10 @@ wedeploy.sh // Submitted by Jung Jin remotewd.com +// WIARD Enterprises : https://wiardweb.com +// Submitted by Kidd Hustle +pages.wiardweb.com + // Wikimedia Labs : https://wikitech.wikimedia.org // Submitted by Arturo Borrero Gonzalez wmflabs.org @@ -13069,12 +13725,30 @@ daemon.panel.gg // WoltLab GmbH : https://www.woltlab.com // Submitted by Tim Düsterhus +woltlab-demo.com myforum.community community-pro.de diskussionsbereich.de community-pro.net meinforum.net +// Woods Valldata : https://www.woodsvalldata.co.uk/ +// Submitted by Chris Whittle +affinitylottery.org.uk +raffleentry.org.uk +weeklylottery.org.uk + +// WP Engine : https://wpengine.com/ +// Submitted by Michael Smith +// Submitted by Brandon DuRette +wpenginepowered.com +js.wpenginepowered.com + +// Wix.com, Inc. : https://www.wix.com +// Submitted by Shahar Talmi +wixsite.com +editorx.io + // XenonCloud GbR: https://xenoncloud.net // Submitted by Julian Uphoff half.host @@ -13117,6 +13791,7 @@ ybo.trade // Yunohost : https://yunohost.org // Submitted by Valentin Grimaud +ynh.fr nohost.me noho.st @@ -13125,10 +13800,6 @@ noho.st za.net za.org -// Zeit, Inc. : https://zeit.domains/ -// Submitted by Olli Vanhoja -now.sh - // Zine EOOD : https://zine.bg/ // Submitted by Martin Angelov bss.design @@ -13139,8 +13810,4 @@ basicserver.io virtualserver.io enterprisecloud.nu -// Mintere : https://mintere.com/ -// Submitted by Ben Aubin -mintere.site - // ===END PRIVATE DOMAINS=== diff --git a/make/data/tzdata/VERSION b/src/java.base/share/data/tzdata/VERSION similarity index 100% rename from make/data/tzdata/VERSION rename to src/java.base/share/data/tzdata/VERSION diff --git a/make/data/tzdata/africa b/src/java.base/share/data/tzdata/africa similarity index 100% rename from make/data/tzdata/africa rename to src/java.base/share/data/tzdata/africa diff --git a/make/data/tzdata/antarctica b/src/java.base/share/data/tzdata/antarctica similarity index 100% rename from make/data/tzdata/antarctica rename to src/java.base/share/data/tzdata/antarctica diff --git a/make/data/tzdata/asia b/src/java.base/share/data/tzdata/asia similarity index 100% rename from make/data/tzdata/asia rename to src/java.base/share/data/tzdata/asia diff --git a/make/data/tzdata/australasia b/src/java.base/share/data/tzdata/australasia similarity index 100% rename from make/data/tzdata/australasia rename to src/java.base/share/data/tzdata/australasia diff --git a/make/data/tzdata/backward b/src/java.base/share/data/tzdata/backward similarity index 100% rename from make/data/tzdata/backward rename to src/java.base/share/data/tzdata/backward diff --git a/make/data/tzdata/etcetera b/src/java.base/share/data/tzdata/etcetera similarity index 100% rename from make/data/tzdata/etcetera rename to src/java.base/share/data/tzdata/etcetera diff --git a/make/data/tzdata/europe b/src/java.base/share/data/tzdata/europe similarity index 100% rename from make/data/tzdata/europe rename to src/java.base/share/data/tzdata/europe diff --git a/make/data/tzdata/factory b/src/java.base/share/data/tzdata/factory similarity index 100% rename from make/data/tzdata/factory rename to src/java.base/share/data/tzdata/factory diff --git a/make/data/tzdata/gmt b/src/java.base/share/data/tzdata/gmt similarity index 100% rename from make/data/tzdata/gmt rename to src/java.base/share/data/tzdata/gmt diff --git a/make/data/tzdata/iso3166.tab b/src/java.base/share/data/tzdata/iso3166.tab similarity index 100% rename from make/data/tzdata/iso3166.tab rename to src/java.base/share/data/tzdata/iso3166.tab diff --git a/make/data/tzdata/jdk11_backward b/src/java.base/share/data/tzdata/jdk11_backward similarity index 100% rename from make/data/tzdata/jdk11_backward rename to src/java.base/share/data/tzdata/jdk11_backward diff --git a/make/data/tzdata/leapseconds b/src/java.base/share/data/tzdata/leapseconds similarity index 100% rename from make/data/tzdata/leapseconds rename to src/java.base/share/data/tzdata/leapseconds diff --git a/make/data/tzdata/northamerica b/src/java.base/share/data/tzdata/northamerica similarity index 100% rename from make/data/tzdata/northamerica rename to src/java.base/share/data/tzdata/northamerica diff --git a/make/data/tzdata/solar87 b/src/java.base/share/data/tzdata/solar87 similarity index 100% rename from make/data/tzdata/solar87 rename to src/java.base/share/data/tzdata/solar87 diff --git a/make/data/tzdata/solar88 b/src/java.base/share/data/tzdata/solar88 similarity index 100% rename from make/data/tzdata/solar88 rename to src/java.base/share/data/tzdata/solar88 diff --git a/make/data/tzdata/solar89 b/src/java.base/share/data/tzdata/solar89 similarity index 100% rename from make/data/tzdata/solar89 rename to src/java.base/share/data/tzdata/solar89 diff --git a/make/data/tzdata/southamerica b/src/java.base/share/data/tzdata/southamerica similarity index 100% rename from make/data/tzdata/southamerica rename to src/java.base/share/data/tzdata/southamerica diff --git a/make/data/tzdata/zone.tab b/src/java.base/share/data/tzdata/zone.tab similarity index 100% rename from make/data/tzdata/zone.tab rename to src/java.base/share/data/tzdata/zone.tab diff --git a/make/data/unicodedata/Blocks.txt b/src/java.base/share/data/unicodedata/Blocks.txt similarity index 100% rename from make/data/unicodedata/Blocks.txt rename to src/java.base/share/data/unicodedata/Blocks.txt diff --git a/make/data/unicodedata/DerivedCoreProperties.txt b/src/java.base/share/data/unicodedata/DerivedCoreProperties.txt similarity index 100% rename from make/data/unicodedata/DerivedCoreProperties.txt rename to src/java.base/share/data/unicodedata/DerivedCoreProperties.txt diff --git a/make/data/unicodedata/NormalizationTest.txt b/src/java.base/share/data/unicodedata/NormalizationTest.txt similarity index 100% rename from make/data/unicodedata/NormalizationTest.txt rename to src/java.base/share/data/unicodedata/NormalizationTest.txt diff --git a/make/data/unicodedata/PropList.txt b/src/java.base/share/data/unicodedata/PropList.txt similarity index 100% rename from make/data/unicodedata/PropList.txt rename to src/java.base/share/data/unicodedata/PropList.txt diff --git a/make/data/unicodedata/PropertyValueAliases.txt b/src/java.base/share/data/unicodedata/PropertyValueAliases.txt similarity index 100% rename from make/data/unicodedata/PropertyValueAliases.txt rename to src/java.base/share/data/unicodedata/PropertyValueAliases.txt diff --git a/make/data/unicodedata/ReadMe.txt b/src/java.base/share/data/unicodedata/ReadMe.txt similarity index 100% rename from make/data/unicodedata/ReadMe.txt rename to src/java.base/share/data/unicodedata/ReadMe.txt diff --git a/make/data/unicodedata/Scripts.txt b/src/java.base/share/data/unicodedata/Scripts.txt similarity index 100% rename from make/data/unicodedata/Scripts.txt rename to src/java.base/share/data/unicodedata/Scripts.txt diff --git a/make/data/unicodedata/SpecialCasing.txt b/src/java.base/share/data/unicodedata/SpecialCasing.txt similarity index 100% rename from make/data/unicodedata/SpecialCasing.txt rename to src/java.base/share/data/unicodedata/SpecialCasing.txt diff --git a/make/data/unicodedata/UnicodeData.txt b/src/java.base/share/data/unicodedata/UnicodeData.txt similarity index 100% rename from make/data/unicodedata/UnicodeData.txt rename to src/java.base/share/data/unicodedata/UnicodeData.txt diff --git a/make/data/unicodedata/auxiliary/GraphemeBreakProperty.txt b/src/java.base/share/data/unicodedata/auxiliary/GraphemeBreakProperty.txt similarity index 100% rename from make/data/unicodedata/auxiliary/GraphemeBreakProperty.txt rename to src/java.base/share/data/unicodedata/auxiliary/GraphemeBreakProperty.txt diff --git a/make/data/unicodedata/auxiliary/GraphemeBreakTest.txt b/src/java.base/share/data/unicodedata/auxiliary/GraphemeBreakTest.txt similarity index 100% rename from make/data/unicodedata/auxiliary/GraphemeBreakTest.txt rename to src/java.base/share/data/unicodedata/auxiliary/GraphemeBreakTest.txt diff --git a/make/data/unicodedata/emoji/emoji-data.txt b/src/java.base/share/data/unicodedata/emoji/emoji-data.txt similarity index 100% rename from make/data/unicodedata/emoji/emoji-data.txt rename to src/java.base/share/data/unicodedata/emoji/emoji-data.txt diff --git a/src/java.base/share/legal/public_suffix.md b/src/java.base/share/legal/public_suffix.md index 3c015a4427b02e1af1a367c57887c93af9158cfc..61d9607177ec33b55ba1adda5a63f8484aa5fe75 100644 --- a/src/java.base/share/legal/public_suffix.md +++ b/src/java.base/share/legal/public_suffix.md @@ -11,7 +11,7 @@ If you do not wish to use the Public Suffix List, you may remove the The Source Code of this file is available under the Mozilla Public License, v. 2.0 and is located at -https://raw.githubusercontent.com/publicsuffix/list/cbbba1d234670453df9c930dfbf510c0474d4301/public_suffix_list.dat. +https://raw.githubusercontent.com/publicsuffix/list/3c213aab32b3c014f171b1673d4ce9b5cd72bf1c/public_suffix_list.dat. If a copy of the MPL was not distributed with this file, you can obtain one at https://mozilla.org/MPL/2.0/. diff --git a/src/java.base/share/man/java.1 b/src/java.base/share/man/java.1 index ea7edb8ef99d771bbde1a32afe8e1c149af9fba5..6750f87e466450c93fc891746969067b073e6f8c 100644 --- a/src/java.base/share/man/java.1 +++ b/src/java.base/share/man/java.1 @@ -1981,6 +1981,34 @@ Allows user to specify VM options in a file, for example, \f[CB]java\ \-XX:VMOptionsFile=/var/my_vm_options\ HelloWorld\f[R]. .RS .RE +.TP +.B \f[CB]\-XX:UseBranchProtection=\f[R]\f[I]mode\f[R] +\f[B]Linux AArch64 only:\f[R] Specifies the branch protection mode. +All options other than \f[CB]none\f[R] require the VM to have been built +with branch protection enabled. +In addition, for full protection, any native libraries provided by +applications should be compiled with the same level of protection. +.RS +.PP +Possible \f[I]mode\f[R] arguments for this option include the following: +.TP +.B \f[CB]none\f[R] +Do not use branch protection. +This is the default value. +.RS +.RE +.TP +.B \f[CB]standard\f[R] +Enables all branch protection modes available on the current platform. +.RS +.RE +.TP +.B \f[CB]pac\-ret\f[R] +Enables protection against ROP based attacks. +(AArch64 8.3+ only) +.RS +.RE +.RE .SH ADVANCED JIT COMPILER OPTIONS FOR JAVA .PP These \f[CB]java\f[R] options control the dynamic just\-in\-time (JIT) @@ -2978,18 +3006,20 @@ different JDK version. .RE .TP .B \f[CB]\-XX:+DTraceAllocProbes\f[R] -\f[B]Linux and macOS:\f[R] Enable \f[CB]dtrace\f[R] tool probes for object allocation. +\f[B]Linux and macOS:\f[R] Enable \f[CB]dtrace\f[R] tool probes for object +allocation. .RS .RE .TP .B \f[CB]\-XX:+DTraceMethodProbes\f[R] -\f[B]Linux and macOS:\f[R] Enable \f[CB]dtrace\f[R] tool probes for method-entry -and method-exit. +\f[B]Linux and macOS:\f[R] Enable \f[CB]dtrace\f[R] tool probes for +method\-entry and method\-exit. .RS .RE .TP .B \f[CB]\-XX:+DTraceMonitorProbes\f[R] -\f[B]Linux and macOS:\f[R] Enable \f[CB]dtrace\f[R] tool probes for monitor events. +\f[B]Linux and macOS:\f[R] Enable \f[CB]dtrace\f[R] tool probes for monitor +events. .RS .RE .TP @@ -4021,8 +4051,9 @@ Example: that affect performance. By default, this option is disabled and \f[CB]dtrace\f[R] performs only standard probes. -Use the combination of these flags instead: \f[CB]\-XX:+DTraceMethodProbes\f[R], -\f[CB]\-XX:+DTraceAllocProbes\f[R], \f[CB]\-XX:+DTraceMonitorProbes\f[R]. +Use the combination of these flags instead: +\f[CB]\-XX:+DTraceMethodProbes\f[R], \f[CB]\-XX:+DTraceAllocProbes\f[R], +\f[CB]\-XX:+DTraceMonitorProbes\f[R]. .RS .RE .TP diff --git a/src/java.base/share/native/libjava/ClassLoader.c b/src/java.base/share/native/libjava/ClassLoader.c index bbdff87b0b312ff549d1456cf88859ff33387b85..301f068070b36cf0cd948718de148570d9b51d46 100644 --- a/src/java.base/share/native/libjava/ClassLoader.c +++ b/src/java.base/share/native/libjava/ClassLoader.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,16 +23,16 @@ * questions. */ -#include #include +#include +#include +#include "check_classname.h" +#include "java_lang_ClassLoader.h" +#include "jlong.h" #include "jni.h" #include "jni_util.h" -#include "jlong.h" #include "jvm.h" -#include "check_classname.h" -#include "java_lang_ClassLoader.h" -#include static JNINativeMethod methods[] = { {"retrieveDirectives", "()Ljava/lang/AssertionStatusDirectives;", (void *)&JVM_AssertionStatusDirectives} @@ -88,7 +88,7 @@ Java_java_lang_ClassLoader_defineClass1(JNIEnv *env, if (data == NULL) { JNU_ThrowNullPointerException(env, 0); - return 0; + return NULL; } /* Work around 4153825. malloc crashes on Solaris when passed a @@ -96,20 +96,27 @@ Java_java_lang_ClassLoader_defineClass1(JNIEnv *env, */ if (length < 0) { JNU_ThrowArrayIndexOutOfBoundsException(env, 0); - return 0; + return NULL; } - body = (jbyte *)malloc(length); + // On AIX malloc(0) returns NULL which looks like an out-of-memory + // condition; so adjust it to malloc(1) + #ifdef _AIX + body = (jbyte *)malloc(length == 0 ? 1 : length); + #else + body = (jbyte *)malloc(length); + #endif - if (body == 0) { + if (body == NULL) { JNU_ThrowOutOfMemoryError(env, 0); - return 0; + return NULL; } (*env)->GetByteArrayRegion(env, data, offset, length, body); - if ((*env)->ExceptionOccurred(env)) + if ((*env)->ExceptionOccurred(env)) { goto free_body; + } if (name != NULL) { utfName = getUTF(env, name, buf, sizeof(buf)); @@ -168,9 +175,9 @@ Java_java_lang_ClassLoader_defineClass2(JNIEnv *env, body = (*env)->GetDirectBufferAddress(env, data); - if (body == 0) { + if (body == NULL) { JNU_ThrowNullPointerException(env, 0); - return 0; + return NULL; } body += offset; @@ -228,7 +235,7 @@ Java_java_lang_ClassLoader_defineClass0(JNIEnv *env, if (data == NULL) { JNU_ThrowNullPointerException(env, 0); - return 0; + return NULL; } /* Work around 4153825. malloc crashes on Solaris when passed a @@ -236,13 +243,20 @@ Java_java_lang_ClassLoader_defineClass0(JNIEnv *env, */ if (length < 0) { JNU_ThrowArrayIndexOutOfBoundsException(env, 0); - return 0; + return NULL; } - body = (jbyte *)malloc(length); - if (body == 0) { + // On AIX malloc(0) returns NULL which looks like an out-of-memory + // condition; so adjust it to malloc(1) + #ifdef _AIX + body = (jbyte *)malloc(length == 0 ? 1 : length); + #else + body = (jbyte *)malloc(length); + #endif + + if (body == NULL) { JNU_ThrowOutOfMemoryError(env, 0); - return 0; + return NULL; } (*env)->GetByteArrayRegion(env, data, offset, length, body); @@ -282,7 +296,7 @@ Java_java_lang_ClassLoader_findBootstrapClass(JNIEnv *env, jclass dummy, char buf[128]; if (classname == NULL) { - return 0; + return NULL; } clname = getUTF(env, classname, buf, sizeof(buf)); @@ -311,7 +325,7 @@ Java_java_lang_ClassLoader_findLoadedClass0(JNIEnv *env, jobject loader, jstring name) { if (name == NULL) { - return 0; + return NULL; } else { return JVM_FindLoadedClass(env, loader, name); } diff --git a/src/java.base/share/native/libjava/NativeLibraries.c b/src/java.base/share/native/libjava/NativeLibraries.c index 71b8b8cac72638642fa1c8ae7ff4aaa8335df305..28b632aecc20c6ae28058f82c8543bfe3a3b5d9a 100644 --- a/src/java.base/share/native/libjava/NativeLibraries.c +++ b/src/java.base/share/native/libjava/NativeLibraries.c @@ -25,13 +25,13 @@ #include #include +#include #include "jni.h" #include "jni_util.h" #include "jlong.h" #include "jvm.h" #include "jdk_internal_loader_NativeLibraries.h" -#include typedef jint (JNICALL *JNI_OnLoad_t)(JavaVM *, void *); typedef void (JNICALL *JNI_OnUnload_t)(JavaVM *, void *); @@ -40,18 +40,17 @@ static jfieldID handleID; static jfieldID jniVersionID; static void *procHandle; - static jboolean initIDs(JNIEnv *env) { if (handleID == 0) { - jclass this = + jclass nlClz = (*env)->FindClass(env, "jdk/internal/loader/NativeLibraries$NativeLibraryImpl"); - if (this == 0) + if (nlClz == 0) return JNI_FALSE; - handleID = (*env)->GetFieldID(env, this, "handle", "J"); + handleID = (*env)->GetFieldID(env, nlClz, "handle", "J"); if (handleID == 0) return JNI_FALSE; - jniVersionID = (*env)->GetFieldID(env, this, "jniVersion", "I"); + jniVersionID = (*env)->GetFieldID(env, nlClz, "jniVersion", "I"); if (jniVersionID == 0) return JNI_FALSE; procHandle = getProcessHandle(); @@ -109,12 +108,12 @@ static void *findJniFunction(JNIEnv *env, void *handle, /* * Class: jdk_internal_loader_NativeLibraries * Method: load - * Signature: (Ljava/lang/String;ZZ)Z + * Signature: (Ljdk/internal/loader/NativeLibraries/NativeLibraryImpl;Ljava/lang/String;ZZ)Z */ JNIEXPORT jboolean JNICALL Java_jdk_internal_loader_NativeLibraries_load - (JNIEnv *env, jobject this, jobject lib, jstring name, - jboolean isBuiltin, jboolean isJNI, jboolean throwExceptionIfFail) + (JNIEnv *env, jclass cls, jobject lib, jstring name, + jboolean isBuiltin, jboolean throwExceptionIfFail) { const char *cname; jint jniVersion; @@ -129,53 +128,52 @@ Java_jdk_internal_loader_NativeLibraries_load if (cname == 0) return JNI_FALSE; handle = isBuiltin ? procHandle : JVM_LoadLibrary(cname, throwExceptionIfFail); - if (isJNI) { - if (handle) { - JNI_OnLoad_t JNI_OnLoad; - JNI_OnLoad = (JNI_OnLoad_t)findJniFunction(env, handle, - isBuiltin ? cname : NULL, - JNI_TRUE); - if (JNI_OnLoad) { - JavaVM *jvm; - (*env)->GetJavaVM(env, &jvm); - jniVersion = (*JNI_OnLoad)(jvm, NULL); - } else { - jniVersion = 0x00010001; - } + if (handle) { + JNI_OnLoad_t JNI_OnLoad; + JNI_OnLoad = (JNI_OnLoad_t)findJniFunction(env, handle, + isBuiltin ? cname : NULL, + JNI_TRUE); + if (JNI_OnLoad) { + JavaVM *jvm; + (*env)->GetJavaVM(env, &jvm); + jniVersion = (*JNI_OnLoad)(jvm, NULL); + } else { + jniVersion = 0x00010001; + } - cause = (*env)->ExceptionOccurred(env); - if (cause) { - (*env)->ExceptionClear(env); - (*env)->Throw(env, cause); - if (!isBuiltin) { - JVM_UnloadLibrary(handle); - } - goto done; + cause = (*env)->ExceptionOccurred(env); + if (cause) { + (*env)->ExceptionClear(env); + (*env)->Throw(env, cause); + if (!isBuiltin) { + JVM_UnloadLibrary(handle); } + goto done; + } - if (!JVM_IsSupportedJNIVersion(jniVersion) || - (isBuiltin && jniVersion < JNI_VERSION_1_8)) { - char msg[256]; - jio_snprintf(msg, sizeof(msg), - "unsupported JNI version 0x%08X required by %s", - jniVersion, cname); - JNU_ThrowByName(env, "java/lang/UnsatisfiedLinkError", msg); - if (!isBuiltin) { - JVM_UnloadLibrary(handle); - } - goto done; - } - (*env)->SetIntField(env, lib, jniVersionID, jniVersion); - } else { - cause = (*env)->ExceptionOccurred(env); - if (cause) { - (*env)->ExceptionClear(env); - (*env)->SetLongField(env, lib, handleID, (jlong)0); - (*env)->Throw(env, cause); + if (!JVM_IsSupportedJNIVersion(jniVersion) || + (isBuiltin && jniVersion < JNI_VERSION_1_8)) { + char msg[256]; + jio_snprintf(msg, sizeof(msg), + "unsupported JNI version 0x%08X required by %s", + jniVersion, cname); + JNU_ThrowByName(env, "java/lang/UnsatisfiedLinkError", msg); + if (!isBuiltin) { + JVM_UnloadLibrary(handle); } goto done; } + (*env)->SetIntField(env, lib, jniVersionID, jniVersion); + } else { + cause = (*env)->ExceptionOccurred(env); + if (cause) { + (*env)->ExceptionClear(env); + (*env)->SetLongField(env, lib, handleID, (jlong)0); + (*env)->Throw(env, cause); + } + goto done; } + (*env)->SetLongField(env, lib, handleID, ptr_to_jlong(handle)); loaded = JNI_TRUE; @@ -187,11 +185,11 @@ Java_jdk_internal_loader_NativeLibraries_load /* * Class: jdk_internal_loader_NativeLibraries * Method: unload - * Signature: (Ljava/lang/String;ZZJ)V + * Signature: (Ljava/lang/String;ZJ)V */ JNIEXPORT void JNICALL Java_jdk_internal_loader_NativeLibraries_unload -(JNIEnv *env, jclass cls, jstring name, jboolean isBuiltin, jboolean isJNI, jlong address) +(JNIEnv *env, jclass cls, jstring name, jboolean isBuiltin, jlong address) { const char *onUnloadSymbols[] = JNI_ONUNLOAD_SYMBOLS; void *handle; @@ -205,15 +203,14 @@ Java_jdk_internal_loader_NativeLibraries_unload return; } handle = jlong_to_ptr(address); - if (isJNI) { - JNI_OnUnload = (JNI_OnUnload_t )findJniFunction(env, handle, - isBuiltin ? cname : NULL, - JNI_FALSE); - if (JNI_OnUnload) { - JavaVM *jvm; - (*env)->GetJavaVM(env, &jvm); - (*JNI_OnUnload)(jvm, NULL); - } + + JNI_OnUnload = (JNI_OnUnload_t )findJniFunction(env, handle, + isBuiltin ? cname : NULL, + JNI_FALSE); + if (JNI_OnUnload) { + JavaVM *jvm; + (*env)->GetJavaVM(env, &jvm); + (*JNI_OnUnload)(jvm, NULL); } if (!isBuiltin) { JVM_UnloadLibrary(handle); @@ -221,24 +218,18 @@ Java_jdk_internal_loader_NativeLibraries_unload JNU_ReleaseStringPlatformChars(env, name, cname); } - /* - * Class: jdk_internal_loader_NativeLibraries + * Class: jdk_internal_loader_NativeLibrary * Method: findEntry0 - * Signature: (Ljava/lang/String;)J + * Signature: (JLjava/lang/String;)J */ JNIEXPORT jlong JNICALL -Java_jdk_internal_loader_NativeLibraries_findEntry0 - (JNIEnv *env, jobject this, jobject lib, jstring name) +Java_jdk_internal_loader_NativeLibrary_findEntry0 + (JNIEnv *env, jclass cls, jlong handle, jstring name) { - jlong handle; const char *cname; jlong res; - if (!initIDs(env)) - return jlong_zero; - - handle = (*env)->GetLongField(env, lib, handleID); cname = (*env)->GetStringUTFChars(env, name, 0); if (cname == 0) return jlong_zero; diff --git a/src/java.base/share/native/libjava/RawNativeLibraries.c b/src/java.base/share/native/libjava/RawNativeLibraries.c new file mode 100644 index 0000000000000000000000000000000000000000..4edc6b34c31138058e222baaff009bc6ac3e1a57 --- /dev/null +++ b/src/java.base/share/native/libjava/RawNativeLibraries.c @@ -0,0 +1,99 @@ +/* + * 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. + */ + +#include +#include +#include + +#include "jni.h" +#include "jni_util.h" +#include "jlong.h" +#include "jvm.h" +#include "jdk_internal_loader_RawNativeLibraries.h" + +static jfieldID handleID; + +static jboolean initIDs(JNIEnv *env) +{ + if (handleID == 0) { + jclass rnlClz = + (*env)->FindClass(env, "jdk/internal/loader/RawNativeLibraries$RawNativeLibraryImpl"); + if (rnlClz == 0) + return JNI_FALSE; + handleID = (*env)->GetFieldID(env, rnlClz, "handle", "J"); + if (handleID == 0) + return JNI_FALSE; + } + return JNI_TRUE; +} + +/* + * Class: jdk_internal_loader_RawNativeLibraries + * Method: Java_jdk_internal_loader_RawNativeLibraries_load0 + * Signature: (Ljdk/internal/loader/RawNativeLibraries/RawNativeLibraryImpl;Ljava/lang/String;)Z + */ +JNIEXPORT jboolean JNICALL +Java_jdk_internal_loader_RawNativeLibraries_load0 + (JNIEnv *env, jclass cls, jobject lib, jstring name) +{ + const char *cname; + void * handle; + + if (!initIDs(env)) + return JNI_FALSE; + + cname = JNU_GetStringPlatformChars(env, name, 0); + if (cname == 0) + return JNI_FALSE; + handle = JVM_LoadLibrary(cname, JNI_FALSE); + (*env)->SetLongField(env, lib, handleID, ptr_to_jlong(handle)); + + JNU_ReleaseStringPlatformChars(env, name, cname); + return handle != 0L; +} + +/* + * Class: jdk_internal_loader_RawNativeLibraries + * Method: unload0 + * Signature: (Ljava/lang/String;J)V + */ +JNIEXPORT void JNICALL Java_jdk_internal_loader_RawNativeLibraries_unload0 + (JNIEnv *env, jclass cls, jstring name, jlong address) +{ + void *handle; + const char *cname; + + if (!initIDs(env)) + return; + cname = JNU_GetStringPlatformChars(env, name, 0); + if (cname == NULL) { + return; + } + handle = jlong_to_ptr(address); + + JVM_UnloadLibrary(handle); + JNU_ReleaseStringPlatformChars(env, name, cname); +} + diff --git a/src/java.base/share/native/libverify/check_code.c b/src/java.base/share/native/libverify/check_code.c index fca549cfc9b1b4cfdbfd4b167fc22372d55915c6..55d6fbcf42a4f552af6ce8443a1f70ed465419d6 100644 --- a/src/java.base/share/native/libverify/check_code.c +++ b/src/java.base/share/native/libverify/check_code.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1994, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1994, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -468,7 +468,8 @@ static void CCout_of_memory (context_type *); /* Because we can longjmp any time, we need to be very careful about * remembering what needs to be freed. */ -static void check_and_push(context_type *context, const void *ptr, int kind); +static void check_and_push_malloc_block(context_type *context, void *ptr); +static void check_and_push_string_utf(context_type *context, const char *ptr); static void pop_and_free(context_type *context); static int signature_to_args_size(const char *method_signature); @@ -604,7 +605,7 @@ class_to_ID(context_type *context, jclass cb, jboolean loadable) unsigned short *pID; const char *name = JVM_GetClassNameUTF(env, cb); - check_and_push(context, name, VM_STRING_UTF); + check_and_push_string_utf(context, name); hash = class_hash_fun(name); pID = &(class_hash->table[hash % HASH_TABLE_SIZE]); while (*pID) { @@ -939,10 +940,10 @@ read_all_code(context_type* context, jclass cb, int num_methods, int i; lengths = malloc(sizeof(int) * num_methods); - check_and_push(context, lengths, VM_MALLOC_BLK); + check_and_push_malloc_block(context, lengths); code = malloc(sizeof(unsigned char*) * num_methods); - check_and_push(context, code, VM_MALLOC_BLK); + check_and_push_malloc_block(context, code); *(lengths_addr) = lengths; *(code_addr) = code; @@ -951,7 +952,7 @@ read_all_code(context_type* context, jclass cb, int num_methods, lengths[i] = JVM_GetMethodIxByteCodeLength(context->env, cb, i); if (lengths[i] > 0) { code[i] = malloc(sizeof(unsigned char) * (lengths[i] + 1)); - check_and_push(context, code[i], VM_MALLOC_BLK); + check_and_push_malloc_block(context, code[i]); JVM_GetMethodIxByteCode(context->env, cb, i, code[i]); } else { code[i] = NULL; @@ -1305,7 +1306,7 @@ verify_opcode_operands(context_type *context, unsigned int inumber, int offset) /* Make sure the constant pool item is the right type. */ verify_constant_pool_type(context, key, kind); methodname = JVM_GetCPMethodNameUTF(env, cb, key); - check_and_push(context, methodname, VM_STRING_UTF); + check_and_push_string_utf(context, methodname); is_constructor = !strcmp(methodname, ""); is_internal = methodname[0] == '<'; pop_and_free(context); @@ -1354,7 +1355,7 @@ verify_opcode_operands(context_type *context, unsigned int inumber, int offset) unsigned int args2; const char *signature = JVM_GetCPMethodSignatureUTF(env, context->class, key); - check_and_push(context, signature, VM_STRING_UTF); + check_and_push_string_utf(context, signature); args1 = signature_to_args_size(signature) + 1; args2 = code[offset + 3]; if (args1 != args2) { @@ -1652,7 +1653,7 @@ initialize_exception_table(context_type *context) classname = JVM_GetCPClassNameUTF(env, context->class, einfo.catchType); - check_and_push(context, classname, VM_STRING_UTF); + check_and_push_string_utf(context, classname); stack_item->item = make_class_info_from_name(context, classname); if (!isAssignableTo(context, stack_item->item, @@ -1807,7 +1808,7 @@ initialize_dataflow(context_type *context) } } signature = JVM_GetMethodIxSignatureUTF(env, cb, mi); - check_and_push(context, signature, VM_STRING_UTF); + check_and_push_string_utf(context, signature); /* Fill in each of the arguments into the registers. */ for (p = signature + 1; *p != JVM_SIGNATURE_ENDFUNC; ) { char fieldchar = signature_to_fieldtype(context, &p, &full_info); @@ -2050,7 +2051,7 @@ pop_stack(context_type *context, unsigned int inumber, stack_info_type *new_stac context->class, operand); char *ip = buffer; - check_and_push(context, signature, VM_STRING_UTF); + check_and_push_string_utf(context, signature); #ifdef DEBUG if (verify_verbose) { print_formatted_fieldname(context, operand); @@ -2076,7 +2077,7 @@ pop_stack(context_type *context, unsigned int inumber, stack_info_type *new_stac operand); char *ip = buffer; const char *p; - check_and_push(context, signature, VM_STRING_UTF); + check_and_push_string_utf(context, signature); #ifdef DEBUG if (verify_verbose) { print_formatted_methodname(context, operand); @@ -2376,7 +2377,7 @@ pop_stack(context_type *context, unsigned int inumber, stack_info_type *new_stac operand); int item; const char *p; - check_and_push(context, signature, VM_STRING_UTF); + check_and_push_string_utf(context, signature); if (opcode == JVM_OPC_invokestatic) { item = 0; } else if (opcode == JVM_OPC_invokeinit) { @@ -2758,7 +2759,7 @@ push_stack(context_type *context, unsigned int inumber, stack_info_type *new_sta const char *signature = JVM_GetCPFieldSignatureUTF(context->env, context->class, operand); - check_and_push(context, signature, VM_STRING_UTF); + check_and_push_string_utf(context, signature); #ifdef DEBUG if (verify_verbose) { print_formatted_fieldname(context, operand); @@ -2780,7 +2781,7 @@ push_stack(context_type *context, unsigned int inumber, stack_info_type *new_sta context->class, operand); const char *result_signature; - check_and_push(context, signature, VM_STRING_UTF); + check_and_push_string_utf(context, signature); result_signature = get_result_signature(signature); if (result_signature++ == NULL) { CCerror(context, "Illegal signature %s", signature); @@ -3621,7 +3622,7 @@ cp_index_to_class_fullinfo(context_type *context, int cp_index, int kind) CCerror(context, "Internal error #5"); } - check_and_push(context, classname, VM_STRING_UTF); + check_and_push_string_utf(context, classname); if (classname[0] == JVM_SIGNATURE_ARRAY) { /* This make recursively call us, in case of a class array */ signature_to_fieldtype(context, &classname, &result); @@ -3822,8 +3823,8 @@ signature_to_fieldtype(context_type *context, assert(finish >= p); length = (int)(finish - p); if (length + 1 > (int)sizeof(buffer_space)) { - buffer = calloc(length + 1, sizeof(char)); - check_and_push(context, buffer, VM_MALLOC_BLK); + buffer = malloc(length + 1); + check_and_push_malloc_block(context, buffer); } memcpy(buffer, p, length); buffer[length] = '\0'; @@ -4142,7 +4143,7 @@ static void free_block(void *ptr, int kind) } } -static void check_and_push(context_type *context, const void *ptr, int kind) +static void check_and_push_common(context_type *context, void *ptr, int kind) { alloc_stack_type *p; if (ptr == 0) @@ -4154,16 +4155,24 @@ static void check_and_push(context_type *context, const void *ptr, int kind) p = malloc(sizeof(alloc_stack_type)); if (p == 0) { /* Make sure we clean up. */ - free_block((void *)ptr, kind); + free_block(ptr, kind); CCout_of_memory(context); } } p->kind = kind; - p->ptr = (void *)ptr; + p->ptr = ptr; p->next = context->allocated_memory; context->allocated_memory = p; } +static void check_and_push_malloc_block(context_type *context, void *ptr) { + check_and_push_common(context, ptr, VM_MALLOC_BLK); +} + +static void check_and_push_string_utf(context_type *context, const char *ptr) { + check_and_push_common(context, (void *)ptr, VM_STRING_UTF); +} + static void pop_and_free(context_type *context) { alloc_stack_type *p = context->allocated_memory; diff --git a/src/java.base/unix/classes/sun/nio/fs/UnixCopyFile.java b/src/java.base/unix/classes/sun/nio/fs/UnixCopyFile.java index 3f98c81b3bf3821958c520986c19004c1db9b1f1..5412748b06c6a2909044dbd859f4a8d8ae02c21f 100644 --- a/src/java.base/unix/classes/sun/nio/fs/UnixCopyFile.java +++ b/src/java.base/unix/classes/sun/nio/fs/UnixCopyFile.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2021, 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 @@ -186,7 +186,7 @@ class UnixCopyFile { } if (sfd >= 0) { source.getFileSystem().copyNonPosixAttributes(sfd, dfd); - close(sfd); + close(sfd, e -> null); } } // copy time stamps last @@ -210,7 +210,7 @@ class UnixCopyFile { done = true; } finally { if (dfd >= 0) - close(dfd); + close(dfd, e -> null); if (!done) { // rollback try { rmdir(target); } catch (UnixException ignore) { } @@ -288,7 +288,7 @@ class UnixCopyFile { } complete = true; } finally { - close(fo); + close(fo, e -> null); // copy of file or attributes failed so rollback if (!complete) { @@ -298,7 +298,7 @@ class UnixCopyFile { } } } finally { - close(fi); + close(fi, e -> null); } } diff --git a/src/java.base/unix/classes/sun/nio/fs/UnixDirectoryStream.java b/src/java.base/unix/classes/sun/nio/fs/UnixDirectoryStream.java index 44b1c70abbb5a849bbfd675c1422f4c976ec420f..3bab00b978201bf0434b5fd25b71dd1c2ee8b388 100644 --- a/src/java.base/unix/classes/sun/nio/fs/UnixDirectoryStream.java +++ b/src/java.base/unix/classes/sun/nio/fs/UnixDirectoryStream.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2016, 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 @@ -67,7 +67,7 @@ class UnixDirectoryStream this.filter = filter; } - protected final UnixPath directory() { + final UnixPath directory() { return dir; } diff --git a/src/java.base/unix/classes/sun/nio/fs/UnixFileAttributeViews.java b/src/java.base/unix/classes/sun/nio/fs/UnixFileAttributeViews.java index 0744be1296df9d4c4a9b0f913ab5b4af29bfa8f0..2ffb3099dbcd2471e80bc1748d2acab781e2caa6 100644 --- a/src/java.base/unix/classes/sun/nio/fs/UnixFileAttributeViews.java +++ b/src/java.base/unix/classes/sun/nio/fs/UnixFileAttributeViews.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2021, 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 @@ -160,7 +160,7 @@ class UnixFileAttributeViews { } } } finally { - close(fd); + close(fd, e -> null); } } } diff --git a/src/java.base/unix/classes/sun/nio/fs/UnixFileStore.java b/src/java.base/unix/classes/sun/nio/fs/UnixFileStore.java index 7947c416a65ca940cf808b8a28ce27c033bdd0be..0d793dc69bbbecfc4e99164cde0d5c9b0e26c527 100644 --- a/src/java.base/unix/classes/sun/nio/fs/UnixFileStore.java +++ b/src/java.base/unix/classes/sun/nio/fs/UnixFileStore.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2021, 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 @@ -197,7 +197,7 @@ abstract class UnixFileStore if (e.errno() == UnixConstants.XATTR_NOT_FOUND) return true; } finally { - UnixNativeDispatcher.close(fd); + UnixNativeDispatcher.close(fd, e -> null); } return false; } diff --git a/src/java.base/unix/classes/sun/nio/fs/UnixFileSystemProvider.java b/src/java.base/unix/classes/sun/nio/fs/UnixFileSystemProvider.java index 44a61827137c5116038433c8f0687432b5718b78..99703d9475578acb685254ccbf8f9a0f8ec6fff1 100644 --- a/src/java.base/unix/classes/sun/nio/fs/UnixFileSystemProvider.java +++ b/src/java.base/unix/classes/sun/nio/fs/UnixFileSystemProvider.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2021, 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 @@ -431,13 +431,14 @@ public abstract class UnixFileSystemProvider dfd2 = dup(dfd1); dp = fdopendir(dfd1); } catch (UnixException x) { + IOException ioe = x.errno() == UnixConstants.ENOTDIR ? + new NotDirectoryException(dir.getPathForExceptionMessage()) : + x.asIOException(dir); if (dfd1 != -1) - UnixNativeDispatcher.close(dfd1); + UnixNativeDispatcher.close(dfd1, e -> null); if (dfd2 != -1) - UnixNativeDispatcher.close(dfd2); - if (x.errno() == UnixConstants.ENOTDIR) - throw new NotDirectoryException(dir.getPathForExceptionMessage()); - x.rethrowAsIOException(dir); + UnixNativeDispatcher.close(dfd2, e -> null); + throw ioe; } return new UnixSecureDirectoryStream(dir, dp, dfd2, filter); } diff --git a/src/java.base/unix/classes/sun/nio/fs/UnixNativeDispatcher.java b/src/java.base/unix/classes/sun/nio/fs/UnixNativeDispatcher.java index 90be5cefae32fc9632bcf6b0c8b296c088ef89ae..4080c08c32ea91233e39a481d6e57949d1f354ed 100644 --- a/src/java.base/unix/classes/sun/nio/fs/UnixNativeDispatcher.java +++ b/src/java.base/unix/classes/sun/nio/fs/UnixNativeDispatcher.java @@ -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 @@ -25,6 +25,8 @@ package sun.nio.fs; +import java.util.function.Function; + /** * Unix system and library calls. */ @@ -90,12 +92,30 @@ class UnixNativeDispatcher { /** * close(int filedes). If fd is -1 this is a no-op. */ - static void close(int fd) { + static void close(int fd) throws UnixException { if (fd != -1) { close0(fd); } } - private static native void close0(int fd); + private static native void close0(int fd) throws UnixException; + + /** + * close(fd). If close fails then the given exception supplier function is + * invoked to produce an exception to throw. If the function returns null + * then no exception is thrown. If close fails and the exception supplier + * function is null, then no exception is thrown. + */ + static + void close(int fd, Function mapper) throws X { + try { + close(fd); + } catch (UnixException e) { + if (mapper != null) { + X ex = mapper.apply(e); + if (ex != null) throw ex; + } + } + } /** * void rewind(FILE* stream); diff --git a/src/java.base/unix/classes/sun/nio/fs/UnixSecureDirectoryStream.java b/src/java.base/unix/classes/sun/nio/fs/UnixSecureDirectoryStream.java index 226effad3ef0f0d565e832800fb1a0a34f80c96d..bedf847c6e71b80488ee4a4c68a86e2742d814d7 100644 --- a/src/java.base/unix/classes/sun/nio/fs/UnixSecureDirectoryStream.java +++ b/src/java.base/unix/classes/sun/nio/fs/UnixSecureDirectoryStream.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2021, 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,7 +61,7 @@ class UnixSecureDirectoryStream ds.writeLock().lock(); try { if (ds.closeImpl()) { - UnixNativeDispatcher.close(dfd); + UnixNativeDispatcher.close(dfd, e -> e.asIOException(ds.directory())); } } finally { ds.writeLock().unlock(); @@ -117,13 +117,14 @@ class UnixSecureDirectoryStream newdfd2 = dup(newdfd1); ptr = fdopendir(newdfd1); } catch (UnixException x) { + IOException ioe = x.errno() == UnixConstants.ENOTDIR ? + new NotDirectoryException(file.toString()) : + x.asIOException(file); if (newdfd1 != -1) - UnixNativeDispatcher.close(newdfd1); + UnixNativeDispatcher.close(newdfd1, e -> null); if (newdfd2 != -1) - UnixNativeDispatcher.close(newdfd2); - if (x.errno() == UnixConstants.ENOTDIR) - throw new NotDirectoryException(file.toString()); - x.rethrowAsIOException(file); + UnixNativeDispatcher.close(newdfd1, e -> null); + throw ioe; } return new UnixSecureDirectoryStream(child, ptr, newdfd2, null); } finally { @@ -422,7 +423,7 @@ class UnixSecureDirectoryStream } } finally { if (file != null) - UnixNativeDispatcher.close(fd); + UnixNativeDispatcher.close(fd, e-> null); } } finally { ds.readLock().unlock(); @@ -504,7 +505,7 @@ class UnixSecureDirectoryStream x.rethrowAsIOException(file); } finally { if (file != null && fd >= 0) - UnixNativeDispatcher.close(fd); + UnixNativeDispatcher.close(fd, e-> null); } } finally { ds.readLock().unlock(); @@ -527,7 +528,7 @@ class UnixSecureDirectoryStream x.rethrowAsIOException(file); } finally { if (file != null && fd >= 0) - UnixNativeDispatcher.close(fd); + UnixNativeDispatcher.close(fd, e-> null); } } finally { ds.readLock().unlock(); diff --git a/src/java.base/unix/classes/sun/nio/fs/UnixUserDefinedFileAttributeView.java b/src/java.base/unix/classes/sun/nio/fs/UnixUserDefinedFileAttributeView.java index 2b62d18cb6f14f60fc84b2f3fe7332dfbf8da768..f568517a2bd865d3c588c52be98da55ac01e24aa 100644 --- a/src/java.base/unix/classes/sun/nio/fs/UnixUserDefinedFileAttributeView.java +++ b/src/java.base/unix/classes/sun/nio/fs/UnixUserDefinedFileAttributeView.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2021, 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 @@ -133,7 +133,7 @@ abstract class UnixUserDefinedFileAttributeView null, "Unable to get list of extended attributes: " + x.getMessage()); } finally { - close(fd); + close(fd, e -> null); } } @@ -157,7 +157,7 @@ abstract class UnixUserDefinedFileAttributeView null, "Unable to get size of extended attribute '" + name + "': " + x.getMessage()); } finally { - close(fd); + close(fd, e -> null); } } @@ -221,7 +221,7 @@ abstract class UnixUserDefinedFileAttributeView throw new FileSystemException(file.getPathForExceptionMessage(), null, "Error reading extended attribute '" + name + "': " + msg); } finally { - close(fd); + close(fd, e -> null); } } @@ -283,7 +283,7 @@ abstract class UnixUserDefinedFileAttributeView null, "Error writing extended attribute '" + name + "': " + x.getMessage()); } finally { - close(fd); + close(fd, e -> null); } } @@ -305,7 +305,7 @@ abstract class UnixUserDefinedFileAttributeView throw new FileSystemException(file.getPathForExceptionMessage(), null, "Unable to delete extended attribute '" + name + "': " + x.getMessage()); } finally { - close(fd); + close(fd, e -> null); } } @@ -346,4 +346,4 @@ abstract class UnixUserDefinedFileAttributeView buffer.release(); } } -} \ No newline at end of file +} diff --git a/src/java.base/unix/native/libjava/java_props_md.c b/src/java.base/unix/native/libjava/java_props_md.c index 36a08d4c156e25613999c3daf1f53e675b632ec9..625dd7fcf4531b2910c615059bbd2fd27998d3aa 100644 --- a/src/java.base/unix/native/libjava/java_props_md.c +++ b/src/java.base/unix/native/libjava/java_props_md.c @@ -488,8 +488,16 @@ GetJavaProperties(JNIEnv *env) #else sprops.user_home = pwent ? strdup(pwent->pw_dir) : NULL; #endif - if (sprops.user_home == NULL) { - sprops.user_home = "?"; + if (sprops.user_home == NULL || sprops.user_home[0] == '\0' || + sprops.user_home[1] == '\0') { + // If the OS supplied home directory is not defined or less than two characters long + // $HOME is the backup source for the home directory, if defined + char* user_home = getenv("HOME"); + if ((user_home != NULL) && (user_home[0] != '\0')) { + sprops.user_home = user_home; + } else { + sprops.user_home = "?"; + } } } diff --git a/src/java.base/unix/native/libnet/Inet4AddressImpl.c b/src/java.base/unix/native/libnet/Inet4AddressImpl.c index bc6c859b841a2511ba1e3d53e503658785f7befa..0edebdbb3ba28ae9f7450dc5b85970a80e46979d 100644 --- a/src/java.base/unix/native/libnet/Inet4AddressImpl.c +++ b/src/java.base/unix/native/libnet/Inet4AddressImpl.c @@ -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 @@ -100,7 +100,7 @@ Java_java_net_Inet4AddressImpl_lookupAllHostAddr(JNIEnv *env, jobject this, JNU_ThrowNullPointerException(env, "host argument is null"); return NULL; } - hostname = JNU_GetStringPlatformChars(env, host, JNI_FALSE); + hostname = JNU_GetStringPlatformChars(env, host, NULL); CHECK_NULL_RETURN(hostname, NULL); // try once, with our static buffer diff --git a/src/java.base/unix/native/libnet/Inet6AddressImpl.c b/src/java.base/unix/native/libnet/Inet6AddressImpl.c index ed0ddbb562c1506fc0426795dc2db64960c92f0c..331151faeb5624322e46822bc48ef16bea35285e 100644 --- a/src/java.base/unix/native/libnet/Inet6AddressImpl.c +++ b/src/java.base/unix/native/libnet/Inet6AddressImpl.c @@ -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 @@ -220,7 +220,7 @@ Java_java_net_Inet6AddressImpl_lookupAllHostAddr(JNIEnv *env, jobject this, JNU_ThrowNullPointerException(env, "host argument is null"); return NULL; } - hostname = JNU_GetStringPlatformChars(env, host, JNI_FALSE); + hostname = JNU_GetStringPlatformChars(env, host, NULL); CHECK_NULL_RETURN(hostname, NULL); // try once, with our static buffer diff --git a/src/java.base/windows/classes/sun/nio/ch/PipeImpl.java b/src/java.base/windows/classes/sun/nio/ch/PipeImpl.java index 005a0a93339e29a6f8ac4cb60bceec6c6f50f5ce..a0e95cc386aaafaeaabbec4c0642f627f837e9b8 100644 --- a/src/java.base/windows/classes/sun/nio/ch/PipeImpl.java +++ b/src/java.base/windows/classes/sun/nio/ch/PipeImpl.java @@ -179,7 +179,7 @@ class PipeImpl * Creates a (TCP) Pipe implementation that supports buffering. */ PipeImpl(SelectorProvider sp) throws IOException { - this(sp, true, false); + this(sp, false, true); } /** diff --git a/src/java.base/windows/classes/sun/nio/ch/WindowsAsynchronousFileChannelImpl.java b/src/java.base/windows/classes/sun/nio/ch/WindowsAsynchronousFileChannelImpl.java index 21972975fa3a777c9a87c46c66a0b4c59581f4b7..a1bacc1fae140684ac6693c86545e129e2c2a53d 100644 --- a/src/java.base/windows/classes/sun/nio/ch/WindowsAsynchronousFileChannelImpl.java +++ b/src/java.base/windows/classes/sun/nio/ch/WindowsAsynchronousFileChannelImpl.java @@ -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 @@ -299,8 +299,10 @@ public class WindowsAsynchronousFileChannelImpl if (!shared && !writing) throw new NonWritableChannelException(); + long len = (size != 0) ? size : Long.MAX_VALUE - Math.max(0, position); + // add to lock table - FileLockImpl fli = addToFileLockTable(position, size, shared); + FileLockImpl fli = addToFileLockTable(position, len, shared); if (fli == null) { Throwable exc = new ClosedChannelException(); if (handler == null) @@ -332,6 +334,9 @@ public class WindowsAsynchronousFileChannelImpl if (!shared && !writing) throw new NonWritableChannelException(); + if (size == 0) + size = Long.MAX_VALUE - Math.max(0, position); + // add to lock table final FileLockImpl fli = addToFileLockTable(position, size, shared); if (fli == null) diff --git a/src/java.base/windows/native/libjava/HostLocaleProviderAdapter_md.c b/src/java.base/windows/native/libjava/HostLocaleProviderAdapter_md.c index b7c2bcc28db60538546cb4508e8af6f715f474bc..ebbad326146d2c14875db3dfcd8b61597cefbf01 100644 --- a/src/java.base/windows/native/libjava/HostLocaleProviderAdapter_md.c +++ b/src/java.base/windows/native/libjava/HostLocaleProviderAdapter_md.c @@ -243,7 +243,7 @@ JNIEXPORT jstring JNICALL Java_sun_util_locale_provider_HostLocaleProviderAdapte JNIEXPORT jstring JNICALL Java_sun_util_locale_provider_HostLocaleProviderAdapterImpl_getDateTimePattern (JNIEnv *env, jclass cls, jint dateStyle, jint timeStyle, jstring jlangtag) { WCHAR pattern[BUFLEN]; - const jchar *langtag = (*env)->GetStringChars(env, jlangtag, JNI_FALSE); + const jchar *langtag = (*env)->GetStringChars(env, jlangtag, NULL); CHECK_NULL_RETURN(langtag, NULL); pattern[0] = L'\0'; @@ -274,7 +274,7 @@ JNIEXPORT jint JNICALL Java_sun_util_locale_provider_HostLocaleProviderAdapterIm (JNIEnv *env, jclass cls, jstring jlangtag) { const jchar *langtag; jint ret; - langtag = (*env)->GetStringChars(env, jlangtag, JNI_FALSE); + langtag = (*env)->GetStringChars(env, jlangtag, NULL); CHECK_NULL_RETURN(langtag, 0); ret = getCalendarID(langtag); (*env)->ReleaseStringChars(env, jlangtag, langtag); @@ -359,18 +359,17 @@ JNIEXPORT jobjectArray JNICALL Java_sun_util_locale_provider_HostLocaleProviderA JNIEXPORT jstring JNICALL Java_sun_util_locale_provider_HostLocaleProviderAdapterImpl_getNumberPattern (JNIEnv *env, jclass cls, jint numberStyle, jstring jlangtag) { const jchar *langtag; - jstring ret; + jstring ret = NULL; WCHAR * pattern; - langtag = (*env)->GetStringChars(env, jlangtag, JNI_FALSE); + langtag = (*env)->GetStringChars(env, jlangtag, NULL); CHECK_NULL_RETURN(langtag, NULL); pattern = getNumberPattern(langtag, numberStyle); - CHECK_NULL_RETURN(pattern, NULL); - + if (!IS_NULL(pattern)) { + ret = (*env)->NewString(env, pattern, (jsize)wcslen(pattern)); + free(pattern); + } (*env)->ReleaseStringChars(env, jlangtag, langtag); - ret = (*env)->NewString(env, pattern, (jsize)wcslen(pattern)); - free(pattern); - return ret; } @@ -383,7 +382,7 @@ JNIEXPORT jboolean JNICALL Java_sun_util_locale_provider_HostLocaleProviderAdapt (JNIEnv *env, jclass cls, jstring jlangtag) { DWORD num; int got; - const jchar *langtag = (*env)->GetStringChars(env, jlangtag, JNI_FALSE); + const jchar *langtag = (*env)->GetStringChars(env, jlangtag, NULL); CHECK_NULL_RETURN(langtag, JNI_FALSE); got = getLocaleInfoWrapper(langtag, LOCALE_IDIGITSUBSTITUTION | LOCALE_RETURN_NUMBER, @@ -402,7 +401,7 @@ JNIEXPORT jstring JNICALL Java_sun_util_locale_provider_HostLocaleProviderAdapte (JNIEnv *env, jclass cls, jstring jlangtag, jstring currencySymbol) { WCHAR buf[BUFLEN]; int got; - const jchar *langtag = (*env)->GetStringChars(env, jlangtag, JNI_FALSE); + const jchar *langtag = (*env)->GetStringChars(env, jlangtag, NULL); CHECK_NULL_RETURN(langtag, currencySymbol); got = getLocaleInfoWrapper(langtag, LOCALE_SCURRENCY, buf, BUFLEN); (*env)->ReleaseStringChars(env, jlangtag, langtag); @@ -423,7 +422,7 @@ JNIEXPORT jchar JNICALL Java_sun_util_locale_provider_HostLocaleProviderAdapterI (JNIEnv *env, jclass cls, jstring jlangtag, jchar decimalSeparator) { WCHAR buf[BUFLEN]; int got; - const jchar *langtag = (*env)->GetStringChars(env, jlangtag, JNI_FALSE); + const jchar *langtag = (*env)->GetStringChars(env, jlangtag, NULL); CHECK_NULL_RETURN(langtag, decimalSeparator); got = getLocaleInfoWrapper(langtag, LOCALE_SDECIMAL, buf, BUFLEN); (*env)->ReleaseStringChars(env, jlangtag, langtag); @@ -444,7 +443,7 @@ JNIEXPORT jchar JNICALL Java_sun_util_locale_provider_HostLocaleProviderAdapterI (JNIEnv *env, jclass cls, jstring jlangtag, jchar groupingSeparator) { WCHAR buf[BUFLEN]; int got; - const jchar *langtag = (*env)->GetStringChars(env, jlangtag, JNI_FALSE); + const jchar *langtag = (*env)->GetStringChars(env, jlangtag, NULL); CHECK_NULL_RETURN(langtag, groupingSeparator); got = getLocaleInfoWrapper(langtag, LOCALE_STHOUSAND, buf, BUFLEN); (*env)->ReleaseStringChars(env, jlangtag, langtag); @@ -465,7 +464,7 @@ JNIEXPORT jstring JNICALL Java_sun_util_locale_provider_HostLocaleProviderAdapte (JNIEnv *env, jclass cls, jstring jlangtag, jstring infinity) { WCHAR buf[BUFLEN]; int got; - const jchar *langtag = (*env)->GetStringChars(env, jlangtag, JNI_FALSE); + const jchar *langtag = (*env)->GetStringChars(env, jlangtag, NULL); CHECK_NULL_RETURN(langtag, infinity); got = getLocaleInfoWrapper(langtag, LOCALE_SPOSINFINITY, buf, BUFLEN); (*env)->ReleaseStringChars(env, jlangtag, langtag); @@ -486,7 +485,7 @@ JNIEXPORT jstring JNICALL Java_sun_util_locale_provider_HostLocaleProviderAdapte (JNIEnv *env, jclass cls, jstring jlangtag, jstring internationalCurrencySymbol) { WCHAR buf[BUFLEN]; int got; - const jchar *langtag = (*env)->GetStringChars(env, jlangtag, JNI_FALSE); + const jchar *langtag = (*env)->GetStringChars(env, jlangtag, NULL); CHECK_NULL_RETURN(langtag, internationalCurrencySymbol); got = getLocaleInfoWrapper(langtag, LOCALE_SINTLSYMBOL, buf, BUFLEN); (*env)->ReleaseStringChars(env, jlangtag, langtag); @@ -507,7 +506,7 @@ JNIEXPORT jchar JNICALL Java_sun_util_locale_provider_HostLocaleProviderAdapterI (JNIEnv *env, jclass cls, jstring jlangtag, jchar minusSign) { WCHAR buf[BUFLEN]; int got; - const jchar *langtag = (*env)->GetStringChars(env, jlangtag, JNI_FALSE); + const jchar *langtag = (*env)->GetStringChars(env, jlangtag, NULL); CHECK_NULL_RETURN(langtag, minusSign); got = getLocaleInfoWrapper(langtag, LOCALE_SNEGATIVESIGN, buf, BUFLEN); (*env)->ReleaseStringChars(env, jlangtag, langtag); @@ -528,7 +527,7 @@ JNIEXPORT jchar JNICALL Java_sun_util_locale_provider_HostLocaleProviderAdapterI (JNIEnv *env, jclass cls, jstring jlangtag, jchar monetaryDecimalSeparator) { WCHAR buf[BUFLEN]; int got; - const jchar *langtag = (*env)->GetStringChars(env, jlangtag, JNI_FALSE); + const jchar *langtag = (*env)->GetStringChars(env, jlangtag, NULL); CHECK_NULL_RETURN(langtag, monetaryDecimalSeparator); got = getLocaleInfoWrapper(langtag, LOCALE_SMONDECIMALSEP, buf, BUFLEN); (*env)->ReleaseStringChars(env, jlangtag, langtag); @@ -549,7 +548,7 @@ JNIEXPORT jstring JNICALL Java_sun_util_locale_provider_HostLocaleProviderAdapte (JNIEnv *env, jclass cls, jstring jlangtag, jstring nan) { WCHAR buf[BUFLEN]; int got; - const jchar *langtag = (*env)->GetStringChars(env, jlangtag, JNI_FALSE); + const jchar *langtag = (*env)->GetStringChars(env, jlangtag, NULL); CHECK_NULL_RETURN(langtag, nan); got = getLocaleInfoWrapper(langtag, LOCALE_SNAN, buf, BUFLEN); (*env)->ReleaseStringChars(env, jlangtag, langtag); @@ -570,7 +569,7 @@ JNIEXPORT jchar JNICALL Java_sun_util_locale_provider_HostLocaleProviderAdapterI (JNIEnv *env, jclass cls, jstring jlangtag, jchar percent) { WCHAR buf[BUFLEN]; int got; - const jchar *langtag = (*env)->GetStringChars(env, jlangtag, JNI_FALSE); + const jchar *langtag = (*env)->GetStringChars(env, jlangtag, NULL); CHECK_NULL_RETURN(langtag, percent); got = getLocaleInfoWrapper(langtag, LOCALE_SPERCENT, buf, BUFLEN); (*env)->ReleaseStringChars(env, jlangtag, langtag); @@ -592,7 +591,7 @@ JNIEXPORT jchar JNICALL Java_sun_util_locale_provider_HostLocaleProviderAdapterI WCHAR buf[BUFLEN]; const jchar *langtag; int got; - langtag = (*env)->GetStringChars(env, jlangtag, JNI_FALSE); + langtag = (*env)->GetStringChars(env, jlangtag, NULL); CHECK_NULL_RETURN(langtag, perMill); got = getLocaleInfoWrapper(langtag, LOCALE_SPERMILLE, buf, BUFLEN); @@ -615,7 +614,7 @@ JNIEXPORT jchar JNICALL Java_sun_util_locale_provider_HostLocaleProviderAdapterI WCHAR buf[BUFLEN]; const jchar *langtag; int got; - langtag = (*env)->GetStringChars(env, jlangtag, JNI_FALSE); + langtag = (*env)->GetStringChars(env, jlangtag, NULL); CHECK_NULL_RETURN(langtag, zeroDigit); got = getLocaleInfoWrapper(langtag, LOCALE_SNATIVEDIGITS, buf, BUFLEN); @@ -639,7 +638,7 @@ JNIEXPORT jint JNICALL Java_sun_util_locale_provider_HostLocaleProviderAdapterIm const jchar *langtag; int got = 0; - langtag = (*env)->GetStringChars(env, jlangtag, JNI_FALSE); + langtag = (*env)->GetStringChars(env, jlangtag, NULL); CHECK_NULL_RETURN(langtag, -1); switch (type) { case sun_util_locale_provider_HostLocaleProviderAdapterImpl_CD_FIRSTDAYOFWEEK: @@ -756,7 +755,7 @@ JNIEXPORT jstring JNICALL Java_sun_util_locale_provider_HostLocaleProviderAdapte return NULL; } - pjChar = (*env)->GetStringChars(env, jStr, JNI_FALSE); + pjChar = (*env)->GetStringChars(env, jStr, NULL); CHECK_NULL_RETURN(pjChar, NULL); got = getLocaleInfoWrapper(pjChar, lcType, buf, BUFLEN); (*env)->ReleaseStringChars(env, jStr, pjChar); @@ -833,7 +832,7 @@ jint getCalendarID(const jchar *langtag) { void replaceCalendarArrayElems(JNIEnv *env, jstring jlangtag, jint calid, jobjectArray jarray, DWORD* pTypes, int offset, int length, int style, BOOL bCal) { WCHAR name[BUFLEN]; - const jchar *langtag = (*env)->GetStringChars(env, jlangtag, JNI_FALSE); + const jchar *langtag = (*env)->GetStringChars(env, jlangtag, NULL); jstring tmp_string; CALTYPE isGenitive = 0; @@ -1023,7 +1022,7 @@ BOOL CALLBACK EnumCalendarInfoProc(LPWSTR lpCalInfoStr, CALID calid, LPWSTR lpRe } jobjectArray getErasImpl(JNIEnv *env, jstring jlangtag, jint calid, jint style, jobjectArray eras) { - const jchar * langtag = (*env)->GetStringChars(env, jlangtag, JNI_FALSE); + const jchar * langtag = (*env)->GetStringChars(env, jlangtag, NULL); WCHAR buf[BUFLEN]; jobjectArray ret = eras; CALTYPE type; diff --git a/src/java.base/windows/native/libnet/Inet4AddressImpl.c b/src/java.base/windows/native/libnet/Inet4AddressImpl.c index 75dfb57eb2f9e1af361ef9148e0f73c6714f254a..33f379024c0b790721de066eb7f38d0483b4c27b 100644 --- a/src/java.base/windows/native/libnet/Inet4AddressImpl.c +++ b/src/java.base/windows/native/libnet/Inet4AddressImpl.c @@ -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. * 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 @@ Java_java_net_Inet4AddressImpl_lookupAllHostAddr(JNIEnv *env, jobject this, JNU_ThrowNullPointerException(env, "host argument is null"); return NULL; } - hostname = JNU_GetStringPlatformChars(env, host, JNI_FALSE); + hostname = JNU_GetStringPlatformChars(env, host, NULL); CHECK_NULL_RETURN(hostname, NULL); // try once, with our static buffer diff --git a/src/java.base/windows/native/libnet/Inet6AddressImpl.c b/src/java.base/windows/native/libnet/Inet6AddressImpl.c index 87908775e99787baf4c0d674c976517e0c3989d1..a011b2fe5fa262896e0853f068a1e5a267d3a9cb 100644 --- a/src/java.base/windows/native/libnet/Inet6AddressImpl.c +++ b/src/java.base/windows/native/libnet/Inet6AddressImpl.c @@ -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 @@ -71,7 +71,7 @@ Java_java_net_Inet6AddressImpl_lookupAllHostAddr(JNIEnv *env, jobject this, JNU_ThrowNullPointerException(env, "host argument is null"); return NULL; } - hostname = JNU_GetStringPlatformChars(env, host, JNI_FALSE); + hostname = JNU_GetStringPlatformChars(env, host, NULL); CHECK_NULL_RETURN(hostname, NULL); // try once, with our static buffer diff --git a/src/java.base/windows/native/libnet/NetworkInterface.c b/src/java.base/windows/native/libnet/NetworkInterface.c index c2f604b24de4741d29ff23039c70f62795fee257..2bad69e1655dfa99cae48e9c730916c31f4d0de7 100644 --- a/src/java.base/windows/native/libnet/NetworkInterface.c +++ b/src/java.base/windows/native/libnet/NetworkInterface.c @@ -176,6 +176,8 @@ int enumInterfaces(JNIEnv *env, netif **netifPP) DWORD i; int lo=0, eth=0, tr=0, fddi=0, ppp=0, sl=0, wlan=0, net=0, wlen=0; + *netifPP = NULL; + /* * Ask the IP Helper library to enumerate the adapters */ @@ -213,9 +215,7 @@ int enumInterfaces(JNIEnv *env, netif **netifPP) "IP Helper Library GetIfTable function failed"); break; } - // this different error code is to handle the case when we call - // GetIpAddrTable in pure IPv6 environment - return -2; + return -1; } /* @@ -373,6 +373,9 @@ int lookupIPAddrTable(JNIEnv *env, MIB_IPADDRTABLE **tablePP) MIB_IPADDRTABLE *tableP; ULONG size; DWORD ret; + + *tablePP = NULL; + /* * Use GetIpAddrTable to enumerate the IP Addresses */ @@ -434,12 +437,15 @@ int enumAddresses_win_ipaddrtable(JNIEnv *env, netif *netifP, netaddr **netaddrP int count = 0; unsigned long mask; + *netaddrPP = NULL; + /* * Iterate through the table to find the addresses with the * matching dwIndex. Ignore 0.0.0.0 addresses. */ - if (tableP == NULL) + if (tableP == NULL) { return 0; + } count = 0; netaddrP = NULL; @@ -452,7 +458,6 @@ int enumAddresses_win_ipaddrtable(JNIEnv *env, netif *netifP, netaddr **netaddrP if (curr == NULL) { JNU_ThrowOutOfMemoryError(env, "Native heap allocation failure"); free_netaddr(netaddrP); - free(tableP); return -1; } @@ -518,9 +523,12 @@ int enumAddresses_win_ipaddrtable(JNIEnv *env, netif *netifP, netaddr **netaddrP int enumAddresses_win(JNIEnv *env, netif *netifP, netaddr **netaddrPP) { MIB_IPADDRTABLE *tableP; int count; + + *netaddrPP = NULL; + int ret = lookupIPAddrTable(env, &tableP); if (ret < 0) { - return NULL; + return ret; } count = enumAddresses_win_ipaddrtable(env, netifP, netaddrPP, tableP); free(tableP); @@ -850,9 +858,7 @@ JNIEXPORT jboolean JNICALL Java_java_net_NetworkInterface_boundInetAddress0 break; } } - } - if (tableP != NULL) { - free(tableP); + free(tableP); } return found; } else { @@ -922,16 +928,16 @@ JNIEXPORT jobject JNICALL Java_java_net_NetworkInterface_getByInetAddress0 /* createNetworkInterface will free addrList */ netifObj = createNetworkInterface(env, curr, count, addrList); break; + } else { + free_netaddr(addrList); } /* on next interface */ curr = curr->next; } - } - - /* release the IP address table */ - if (tableP != NULL) + /* release the IP address table */ free(tableP); + } /* release the interface list */ free_netif(ifList); @@ -948,7 +954,7 @@ JNIEXPORT jobjectArray JNICALL Java_java_net_NetworkInterface_getAll (JNIEnv *env, jclass cls) { int count; - netif *ifList = NULL, *curr; + netif *ifList, *curr; jobjectArray netIFArr; jint arr_index; diff --git a/src/java.base/windows/native/libnet/NetworkInterface_winXP.c b/src/java.base/windows/native/libnet/NetworkInterface_winXP.c index 6483cd9eb80898b6403041434a9e2db76f2d45d7..08b6acf751a933d981bdcaf0b98ffdf342e7c76b 100644 --- a/src/java.base/windows/native/libnet/NetworkInterface_winXP.c +++ b/src/java.base/windows/native/libnet/NetworkInterface_winXP.c @@ -79,6 +79,8 @@ int getAdapters (JNIEnv *env, int flags, IP_ADAPTER_ADDRESSES **adapters) { ULONG len; int try; + *adapters = NULL; + adapterInfo = (IP_ADAPTER_ADDRESSES *) malloc(BUFF_SIZE); if (adapterInfo == NULL) { JNU_ThrowByName(env, "java/lang/OutOfMemoryError", @@ -233,8 +235,6 @@ IP_ADAPTER_ADDRESSES *getAdapter (JNIEnv *env, jint index) { return ret; } -static int ipinflen = 2048; - /* */ int getAllInterfacesAndAddresses (JNIEnv *env, netif **netifPP) @@ -242,23 +242,18 @@ int getAllInterfacesAndAddresses (JNIEnv *env, netif **netifPP) int ret, flags; MIB_IPADDRTABLE *tableP; IP_ADAPTER_ADDRESSES *ptr, *adapters=NULL; - ULONG len=ipinflen, count=0; + ULONG count=0; netif *nif=NULL, *dup_nif, *last=NULL, *loopif=NULL, *curr; int tun=0, net=0; - *netifPP = NULL; /* * Get the IPv4 interfaces. This information is the same * as what previous JDK versions would return. */ ret = enumInterfaces(env, netifPP); - if (ret == -1) { + if (ret < 0) { return -1; - } else if( ret == -2){ - if ((*env)->ExceptionCheck(env)) { - (*env)->ExceptionClear(env); - } } else { count = ret; } @@ -274,20 +269,23 @@ int getAllInterfacesAndAddresses (JNIEnv *env, netif **netifPP) // Retrieve IPv4 addresses with the IP Helper API curr = *netifPP; ret = lookupIPAddrTable(env, &tableP); - if (ret < 0) { + if (ret == -1) { + free_netif(*netifPP); return -1; + } else if (ret == -2) { + // Clear the exception and continue. + if ((*env)->ExceptionCheck(env)) { + (*env)->ExceptionClear(env); + } + tableP = NULL; } while (curr != NULL) { netaddr *netaddrP; ret = enumAddresses_win_ipaddrtable(env, curr, &netaddrP, tableP); - if (ret == -1) { + if (ret < 0) { + free_netif(*netifPP); free(tableP); return -1; - } else if (ret == -2) { - if ((*env)->ExceptionCheck(env)) { - (*env)->ExceptionClear(env); - } - break; } else{ curr->addrs = netaddrP; curr->naddrs += ret; @@ -301,7 +299,8 @@ int getAllInterfacesAndAddresses (JNIEnv *env, netif **netifPP) flags |= GAA_FLAG_INCLUDE_PREFIX; ret = getAdapters (env, flags, &adapters); if (ret != ERROR_SUCCESS) { - goto err; + free_netif(*netifPP); + return -1; } /* Now get the IPv6 information. This includes: @@ -340,6 +339,9 @@ int getAllInterfacesAndAddresses (JNIEnv *env, netif **netifPP) */ nif->ipv6Index = ptr->Ipv6IfIndex; c = getAddrsFromAdapter(ptr, &nif->addrs); + if (c == -1) { + goto err; + } nif->naddrs += c; break; } @@ -378,6 +380,7 @@ int getAllInterfacesAndAddresses (JNIEnv *env, netif **netifPP) nif->name = malloc (strlen(newname)+1); nif->displayName = malloc (wcslen(ptr->FriendlyName)*2+2); if (nif->name == 0 || nif->displayName == 0) { + free(nif); goto err; } strcpy (nif->name, newname); @@ -390,7 +393,11 @@ int getAllInterfacesAndAddresses (JNIEnv *env, netif **netifPP) nif->ipv6Index = ptr->Ipv6IfIndex; nif->hasIpv6Address = TRUE; - last->next = nif; + if (last) { + last->next = nif; + } else { + *netifPP = nif; + } last = nif; count++; c = getAddrsFromAdapter(ptr, &nif->addrs); @@ -585,6 +592,8 @@ static jobject createNetworkInterfaceXP(JNIEnv *env, netif *ifs) if ((*env)->ExceptionCheck(env)) { (*env)->ExceptionClear(env); } + netaddrCount = 0; + netaddrPToFree = NULL; } netaddrP = netaddrPToFree; } @@ -826,7 +835,7 @@ JNIEXPORT jobjectArray JNICALL Java_java_net_NetworkInterface_getAll_XP (JNIEnv *env, jclass cls) { int count; - netif *ifList = NULL, *curr; + netif *ifList, *curr; jobjectArray netIFArr; jint arr_index; diff --git a/src/java.compiler/share/classes/javax/annotation/processing/AbstractProcessor.java b/src/java.compiler/share/classes/javax/annotation/processing/AbstractProcessor.java index 7754105a8d4c71cb9bf401d216b18eae0055332f..a44a755650da7c1366da1e0af167eea1a7700eb5 100644 --- a/src/java.compiler/share/classes/javax/annotation/processing/AbstractProcessor.java +++ b/src/java.compiler/share/classes/javax/annotation/processing/AbstractProcessor.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2020, 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 @@ -53,9 +53,6 @@ import javax.tools.Diagnostic; * general {@link javax.annotation.processing.Processor Processor} * contract for that method is obeyed. * - * @author Joseph D. Darcy - * @author Scott Seligman - * @author Peter von der Ahé * @since 1.6 */ public abstract class AbstractProcessor implements Processor { diff --git a/src/java.compiler/share/classes/javax/annotation/processing/Completion.java b/src/java.compiler/share/classes/javax/annotation/processing/Completion.java index 58c158279d357183c031bb33bf19b51c402361bc..7427b06195c3bf426f8ff6cb5ecb58e8dc58bab0 100644 --- a/src/java.compiler/share/classes/javax/annotation/processing/Completion.java +++ b/src/java.compiler/share/classes/javax/annotation/processing/Completion.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, 2020, 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 @@ -30,9 +30,6 @@ package javax.annotation.processing; * annotation. A completion is text meant to be inserted into a * program as part of an annotation. * - * @author Joseph D. Darcy - * @author Scott Seligman - * @author Peter von der Ahé * @since 1.6 */ public interface Completion { diff --git a/src/java.compiler/share/classes/javax/annotation/processing/Completions.java b/src/java.compiler/share/classes/javax/annotation/processing/Completions.java index 5b476afec65ed6fc83a53fa5c71e6b47e6ed1f77..27d105f88ff3b4500ad4deb2b0f572e3bf81d9eb 100644 --- a/src/java.compiler/share/classes/javax/annotation/processing/Completions.java +++ b/src/java.compiler/share/classes/javax/annotation/processing/Completions.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, 2020, 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 @@ -28,9 +28,6 @@ package javax.annotation.processing; /** * Utility class for assembling {@link Completion} objects. * - * @author Joseph D. Darcy - * @author Scott Seligman - * @author Peter von der Ahé * @since 1.6 */ public class Completions { diff --git a/src/java.compiler/share/classes/javax/annotation/processing/Filer.java b/src/java.compiler/share/classes/javax/annotation/processing/Filer.java index 80c01228ed6c8945771f0c33dbfb3fa15127ca58..59a2681de8dbe89b9a05cae1b91b6fbc36a54849 100644 --- a/src/java.compiler/share/classes/javax/annotation/processing/Filer.java +++ b/src/java.compiler/share/classes/javax/annotation/processing/Filer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2021, 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 @@ -132,9 +132,6 @@ import java.io.IOException; * factories instead of public constructors so that only subclass * instances would be presented to clients of the parent class. * - * @author Joseph D. Darcy - * @author Scott Seligman - * @author Peter von der Ahé * @since 1.6 */ public interface Filer { diff --git a/src/java.compiler/share/classes/javax/annotation/processing/FilerException.java b/src/java.compiler/share/classes/javax/annotation/processing/FilerException.java index 0e7d9cdda76a74a7974250611e704ef68a5dedc4..26ee999e5335a8900855d14b2ebf09003b1e6e15 100644 --- a/src/java.compiler/share/classes/javax/annotation/processing/FilerException.java +++ b/src/java.compiler/share/classes/javax/annotation/processing/FilerException.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2020, 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 @@ -35,9 +35,6 @@ import java.io.IOException; * interface or package, and not creating files for classes or * interfaces with invalid names. * - * @author Joseph D. Darcy - * @author Scott Seligman - * @author Peter von der Ahé * @since 1.6 */ public class FilerException extends IOException { diff --git a/src/java.compiler/share/classes/javax/annotation/processing/Messager.java b/src/java.compiler/share/classes/javax/annotation/processing/Messager.java index a5f7add18f6eb105af2959834249ad35d4ac3658..11127a73108b0dd13f12a33cb426fb87c515bbfb 100644 --- a/src/java.compiler/share/classes/javax/annotation/processing/Messager.java +++ b/src/java.compiler/share/classes/javax/annotation/processing/Messager.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2021, 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 @@ -46,9 +46,6 @@ import javax.lang.model.element.*; * choose to present this information in a different fashion, such as * messages in a window. * - * @author Joseph D. Darcy - * @author Scott Seligman - * @author Peter von der Ahé * @see ProcessingEnvironment#getLocale * @since 1.6 */ diff --git a/src/java.compiler/share/classes/javax/annotation/processing/ProcessingEnvironment.java b/src/java.compiler/share/classes/javax/annotation/processing/ProcessingEnvironment.java index 2a31129c3191df77bf0cd5cee9880f041a1e2c27..9c04acb3e0bf335b0f2461eae0db75e383f8cbee 100644 --- a/src/java.compiler/share/classes/javax/annotation/processing/ProcessingEnvironment.java +++ b/src/java.compiler/share/classes/javax/annotation/processing/ProcessingEnvironment.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2021, 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 @@ -53,9 +53,6 @@ import javax.lang.model.util.Types; * of a wrapper class must know whether or not the same base facility * object has been wrapped before.) * - * @author Joseph D. Darcy - * @author Scott Seligman - * @author Peter von der Ahé * @since 1.6 */ public interface ProcessingEnvironment { diff --git a/src/java.compiler/share/classes/javax/annotation/processing/Processor.java b/src/java.compiler/share/classes/javax/annotation/processing/Processor.java index d70910c9d49a2e8fe16affcc065ef3fbc33fbc97..01de039d2c2c8bd88c05a579c4ca26cdf9c10d3e 100644 --- a/src/java.compiler/share/classes/javax/annotation/processing/Processor.java +++ b/src/java.compiler/share/classes/javax/annotation/processing/Processor.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2021, 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 @@ -198,9 +198,6 @@ import javax.lang.model.SourceVersion; * to extend {@link AbstractProcessor} rather than implementing this * interface directly. * - * @author Joseph D. Darcy - * @author Scott Seligman - * @author Peter von der Ahé * @since 1.6 */ public interface Processor { diff --git a/src/java.compiler/share/classes/javax/annotation/processing/RoundEnvironment.java b/src/java.compiler/share/classes/javax/annotation/processing/RoundEnvironment.java index 6323bda133914568927acb8d95210b31d88f3914..4c8144016472d735c7c02038f6e1934b814a6423 100644 --- a/src/java.compiler/share/classes/javax/annotation/processing/RoundEnvironment.java +++ b/src/java.compiler/share/classes/javax/annotation/processing/RoundEnvironment.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2021, 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 @@ -37,9 +37,6 @@ import java.lang.annotation.Annotation; * implementing this interface} so that the processor can query for * information about a round of annotation processing. * - * @author Joseph D. Darcy - * @author Scott Seligman - * @author Peter von der Ahé * @since 1.6 */ public interface RoundEnvironment { diff --git a/src/java.compiler/share/classes/javax/annotation/processing/SupportedAnnotationTypes.java b/src/java.compiler/share/classes/javax/annotation/processing/SupportedAnnotationTypes.java index bb6c87ef7e2212acbdfd95bdf4e022951c4a3df0..8eb2fc3fd2f0e16719873e0c0f31f9ea6a479b7b 100644 --- a/src/java.compiler/share/classes/javax/annotation/processing/SupportedAnnotationTypes.java +++ b/src/java.compiler/share/classes/javax/annotation/processing/SupportedAnnotationTypes.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2020, 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 @@ -38,9 +38,6 @@ import static java.lang.annotation.ElementType.*; * Processor#getSupportedAnnotationTypes strings conforming to the * grammar} should be used as values. * - * @author Joseph D. Darcy - * @author Scott Seligman - * @author Peter von der Ahé * @since 1.6 */ @Documented diff --git a/src/java.compiler/share/classes/javax/annotation/processing/SupportedOptions.java b/src/java.compiler/share/classes/javax/annotation/processing/SupportedOptions.java index 7f8817a011cc099609aaa44426f49c398ea9af31..321a0a03df2ee2dc3710cc7f72a427c4b7ce2943 100644 --- a/src/java.compiler/share/classes/javax/annotation/processing/SupportedOptions.java +++ b/src/java.compiler/share/classes/javax/annotation/processing/SupportedOptions.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2020, 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 @@ -37,9 +37,6 @@ import static java.lang.annotation.ElementType.*; * Processor#getSupportedOptions strings conforming to the * grammar} should be used as values. * - * @author Joseph D. Darcy - * @author Scott Seligman - * @author Peter von der Ahé * @since 1.6 */ @Documented diff --git a/src/java.compiler/share/classes/javax/annotation/processing/SupportedSourceVersion.java b/src/java.compiler/share/classes/javax/annotation/processing/SupportedSourceVersion.java index 18fa42075a83ca421f3008dd51345c4d02cbfa73..487bfce686c7906986e0bc581aefe75e45111ad9 100644 --- a/src/java.compiler/share/classes/javax/annotation/processing/SupportedSourceVersion.java +++ b/src/java.compiler/share/classes/javax/annotation/processing/SupportedSourceVersion.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2020, 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 @@ -38,9 +38,6 @@ import javax.lang.model.SourceVersion; * result from the value of this annotation, as done by {@link * AbstractProcessor#getSupportedSourceVersion}. * - * @author Joseph D. Darcy - * @author Scott Seligman - * @author Peter von der Ahé * @since 1.6 */ @Documented diff --git a/src/java.compiler/share/classes/javax/annotation/processing/package-info.java b/src/java.compiler/share/classes/javax/annotation/processing/package-info.java index 64bbf611032c3881c0e1e0df7a9722fb9334ba94..fec9c2900585e3dd09661c7b4e1bea96e0bf7e10 100644 --- a/src/java.compiler/share/classes/javax/annotation/processing/package-info.java +++ b/src/java.compiler/share/classes/javax/annotation/processing/package-info.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2006, 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 @@ -35,9 +35,6 @@ *

      Unless otherwise specified, methods in this package will throw * a {@code NullPointerException} if given a {@code null} argument. * - * @author Joseph D. Darcy - * @author Scott Seligman - * @author Peter von der Ahé * @since 1.6 */ package javax.annotation.processing; diff --git a/src/java.compiler/share/classes/javax/lang/model/SourceVersion.java b/src/java.compiler/share/classes/javax/lang/model/SourceVersion.java index 7d29f9011bf0b392414268ba1211e022079d4a4a..c31a2eb7d8e685901105d42ade3f7961eb504200 100644 --- a/src/java.compiler/share/classes/javax/lang/model/SourceVersion.java +++ b/src/java.compiler/share/classes/javax/lang/model/SourceVersion.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2021, 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 @@ -39,9 +39,6 @@ import java.util.HashSet; *

      Note that additional source version constants will be added to * model future releases of the language. * - * @author Joseph D. Darcy - * @author Scott Seligman - * @author Peter von der Ahé * @since 1.6 */ public enum SourceVersion { diff --git a/src/java.compiler/share/classes/javax/lang/model/UnknownEntityException.java b/src/java.compiler/share/classes/javax/lang/model/UnknownEntityException.java index 3e2cee42400a2331ece4be02f9f85b5070c80749..2ca3a1d988c765d3207f186415b9cdb7e9e2b8c3 100644 --- a/src/java.compiler/share/classes/javax/lang/model/UnknownEntityException.java +++ b/src/java.compiler/share/classes/javax/lang/model/UnknownEntityException.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2020, 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 @@ -32,7 +32,6 @@ package javax.lang.model; * this exception may be thrown by visitors to indicate that the * visitor was created for a prior version of the language. * - * @author Joseph D. Darcy * @see javax.lang.model.element.UnknownElementException * @see javax.lang.model.element.UnknownAnnotationValueException * @see javax.lang.model.type.UnknownTypeException diff --git a/src/java.compiler/share/classes/javax/lang/model/element/AnnotationMirror.java b/src/java.compiler/share/classes/javax/lang/model/element/AnnotationMirror.java index e1c3a86883d311a7f590b4b93462b505b43fe062..8986463832518c0b0aac29b97784ab5131b1e6d7 100644 --- a/src/java.compiler/share/classes/javax/lang/model/element/AnnotationMirror.java +++ b/src/java.compiler/share/classes/javax/lang/model/element/AnnotationMirror.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2021, 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,9 +36,6 @@ import javax.lang.model.type.DeclaredType; * method. There is no guarantee that any particular annotation will * always be represented by the same object. * - * @author Joseph D. Darcy - * @author Scott Seligman - * @author Peter von der Ahé * @since 1.6 */ public interface AnnotationMirror { diff --git a/src/java.compiler/share/classes/javax/lang/model/element/AnnotationValue.java b/src/java.compiler/share/classes/javax/lang/model/element/AnnotationValue.java index ed7a180537e0aa57bffc04ca884de6e6d7b00352..77521dac191659c7410c8a03c24bc96dd9455b5d 100644 --- a/src/java.compiler/share/classes/javax/lang/model/element/AnnotationValue.java +++ b/src/java.compiler/share/classes/javax/lang/model/element/AnnotationValue.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2020, 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 @@ -37,9 +37,6 @@ package javax.lang.model.element; * (representing the elements, in declared order, if the value is an array) *

    * - * @author Joseph D. Darcy - * @author Scott Seligman - * @author Peter von der Ahé * @since 1.6 */ public interface AnnotationValue { diff --git a/src/java.compiler/share/classes/javax/lang/model/element/AnnotationValueVisitor.java b/src/java.compiler/share/classes/javax/lang/model/element/AnnotationValueVisitor.java index be66b95e4fc60e033dcd98cf568a1c06272989d8..71292a4ee3cb5a3e3bb95979aa360607c734a15d 100644 --- a/src/java.compiler/share/classes/javax/lang/model/element/AnnotationValueVisitor.java +++ b/src/java.compiler/share/classes/javax/lang/model/element/AnnotationValueVisitor.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2020, 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 @@ -115,9 +115,6 @@ import javax.lang.model.util.*; * * @param the return type of this visitor's methods * @param

    the type of the additional parameter to this visitor's methods. - * @author Joseph D. Darcy - * @author Scott Seligman - * @author Peter von der Ahé * @since 1.6 */ public interface AnnotationValueVisitor { diff --git a/src/java.compiler/share/classes/javax/lang/model/element/Element.java b/src/java.compiler/share/classes/javax/lang/model/element/Element.java index 0cb49fd985f32ed92cf4df359a8570d4847bc9e9..df2ecee8243abdafa5121761706222f4ae1ab72e 100644 --- a/src/java.compiler/share/classes/javax/lang/model/element/Element.java +++ b/src/java.compiler/share/classes/javax/lang/model/element/Element.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2021, 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 @@ -52,9 +52,6 @@ import javax.lang.model.util.*; * hierarchy since an implementation may choose to have a single object * implement multiple {@code Element} subinterfaces. * - * @author Joseph D. Darcy - * @author Scott Seligman - * @author Peter von der Ahé * @see Elements * @see TypeMirror * @since 1.6 diff --git a/src/java.compiler/share/classes/javax/lang/model/element/ElementKind.java b/src/java.compiler/share/classes/javax/lang/model/element/ElementKind.java index 2639358cb74b50d134e17f8c470f704d91c63a07..4190e2acdab31579a4f7400c62a2ec223c24719d 100644 --- a/src/java.compiler/share/classes/javax/lang/model/element/ElementKind.java +++ b/src/java.compiler/share/classes/javax/lang/model/element/ElementKind.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2021, 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 @@ -32,9 +32,6 @@ package javax.lang.model.element; * to accommodate new, currently unknown, language structures added to * future versions of the Java programming language. * - * @author Joseph D. Darcy - * @author Scott Seligman - * @author Peter von der Ahé * @see Element * @since 1.6 */ @@ -136,7 +133,6 @@ public enum ElementKind { * * @return {@code true} if this is a kind of class */ - @SuppressWarnings("preview") public boolean isClass() { return this == CLASS || this == ENUM || this == RECORD; } @@ -151,6 +147,17 @@ public enum ElementKind { return this == INTERFACE || this == ANNOTATION_TYPE; } + /** + * {@return {@code true} if this is a kind of declared type, a + * {@linkplain #isClass() class} or an {@linkplain #isInterface() + * interface}, and {@code false} otherwise} + * + * @since 19 + */ + public boolean isDeclaredType() { + return isClass() || isInterface(); + } + /** * Returns {@code true} if this is a kind of field: * either {@code FIELD} or {@code ENUM_CONSTANT}. @@ -160,4 +167,50 @@ public enum ElementKind { public boolean isField() { return this == FIELD || this == ENUM_CONSTANT; } + + /** + * Returns {@code true} if this is a kind of executable: either + * {@code METHOD} or {@code CONSTRUCTOR} or {@code STATIC_INIT} or + * {@code INSTANCE_INIT}. + * + * @return {@code true} if this is a kind of executable + * @since 19 + */ + public boolean isExecutable() { + return switch(this) { + case METHOD, CONSTRUCTOR, STATIC_INIT, INSTANCE_INIT -> true; + default -> false; + }; + } + + /** + * Returns {@code true} if this is a kind of initializer: either + * {@code STATIC_INIT} or {@code INSTANCE_INIT}. + * + * @return {@code true} if this is a kind of initializer + * @since 19 + */ + public boolean isInitializer() { + return switch(this) { + case STATIC_INIT, INSTANCE_INIT -> true; + default -> false; + }; + } + /** + * Returns {@code true} if this is a kind of variable: including + * {@code ENUM_CONSTANT}, {@code FIELD}, {@code PARAMETER}, + * {@code LOCAL_VARIABLE}, {@code EXCEPTION_PARAMETER}, + * {@code RESOURCE_VARIABLE}, and {@code BINDING_VARIABLE}. + * + * @return {@code true} if this is a kind of variable + * @since 19 + */ + public boolean isVariable() { + return switch(this) { + case ENUM_CONSTANT, FIELD, PARAMETER, + LOCAL_VARIABLE, EXCEPTION_PARAMETER, RESOURCE_VARIABLE, + BINDING_VARIABLE -> true; + default -> false; + }; + } } diff --git a/src/java.compiler/share/classes/javax/lang/model/element/ElementVisitor.java b/src/java.compiler/share/classes/javax/lang/model/element/ElementVisitor.java index e921a9ba2d63de986c1d057f6bcfaa04973a2dae..03ca36ba434efef1c103ed6d060f493714c801fe 100644 --- a/src/java.compiler/share/classes/javax/lang/model/element/ElementVisitor.java +++ b/src/java.compiler/share/classes/javax/lang/model/element/ElementVisitor.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2021, 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 @@ -117,9 +117,6 @@ import javax.lang.model.util.*; * methods. Use {@code Void} for visitors that do not need an * additional parameter. * - * @author Joseph D. Darcy - * @author Scott Seligman - * @author Peter von der Ahé * @since 1.6 */ public interface ElementVisitor { diff --git a/src/java.compiler/share/classes/javax/lang/model/element/ExecutableElement.java b/src/java.compiler/share/classes/javax/lang/model/element/ExecutableElement.java index 882917b21b53bca8c40a8b1cd90f1a0e768deb86..3bc0457755260a85244d256aa13aa333213a4cd1 100644 --- a/src/java.compiler/share/classes/javax/lang/model/element/ExecutableElement.java +++ b/src/java.compiler/share/classes/javax/lang/model/element/ExecutableElement.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2021, 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 @@ -33,9 +33,6 @@ import javax.lang.model.type.*; * instance) of a class or interface, including annotation type * elements. * - * @author Joseph D. Darcy - * @author Scott Seligman - * @author Peter von der Ahé * @see ExecutableType * @since 1.6 */ diff --git a/src/java.compiler/share/classes/javax/lang/model/element/Modifier.java b/src/java.compiler/share/classes/javax/lang/model/element/Modifier.java index dfbd76d2bf1367e0057a5c0930d5d729b0a3cdf6..9dcd8390b60d6ca557a2e5a124f1b300bdbca3d5 100644 --- a/src/java.compiler/share/classes/javax/lang/model/element/Modifier.java +++ b/src/java.compiler/share/classes/javax/lang/model/element/Modifier.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2021, 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 @@ -44,9 +44,6 @@ package javax.lang.model.element; * @jls 8.8.3 Constructor Modifiers * @jls 9.1.1 Interface Modifiers * - * @author Joseph D. Darcy - * @author Scott Seligman - * @author Peter von der Ahé * @since 1.6 */ diff --git a/src/java.compiler/share/classes/javax/lang/model/element/Name.java b/src/java.compiler/share/classes/javax/lang/model/element/Name.java index 9e40bcf740076b9e2721a8e581c3214c7338b070..70bc5e0ad6361e2961e75722c572ca8f00a4ddf7 100644 --- a/src/java.compiler/share/classes/javax/lang/model/element/Name.java +++ b/src/java.compiler/share/classes/javax/lang/model/element/Name.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, 2020, 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 @@ -46,9 +46,6 @@ package javax.lang.model.element; * to each other, including successive annotation processing * {@linkplain javax.annotation.processing.RoundEnvironment rounds}. * - * @author Joseph D. Darcy - * @author Scott Seligman - * @author Peter von der Ahé * @see javax.lang.model.util.Elements#getName * @since 1.6 */ diff --git a/src/java.compiler/share/classes/javax/lang/model/element/NestingKind.java b/src/java.compiler/share/classes/javax/lang/model/element/NestingKind.java index 62cc65d8c5ad65723fb1bd05b6e091bb9bbc4c06..7f8cee373f70de03306edd8113d0a2b520f0b6ea 100644 --- a/src/java.compiler/share/classes/javax/lang/model/element/NestingKind.java +++ b/src/java.compiler/share/classes/javax/lang/model/element/NestingKind.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2020, 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 @@ -76,9 +76,6 @@ package javax.lang.model.element; * } * * - * @author Joseph D. Darcy - * @author Scott Seligman - * @author Peter von der Ahé * @since 1.6 */ public enum NestingKind { diff --git a/src/java.compiler/share/classes/javax/lang/model/element/PackageElement.java b/src/java.compiler/share/classes/javax/lang/model/element/PackageElement.java index 42d62cb289c34edd5ae2f470b65d5f061ec799ec..f16daca0b0605f8b488a9a685ce6071f30d3ad29 100644 --- a/src/java.compiler/share/classes/javax/lang/model/element/PackageElement.java +++ b/src/java.compiler/share/classes/javax/lang/model/element/PackageElement.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2020, 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 @@ -32,9 +32,6 @@ import javax.lang.model.type.TypeMirror; * Represents a package program element. Provides access to information * about the package and its members. * - * @author Joseph D. Darcy - * @author Scott Seligman - * @author Peter von der Ahé * @see javax.lang.model.util.Elements#getPackageOf * @since 1.6 */ diff --git a/src/java.compiler/share/classes/javax/lang/model/element/Parameterizable.java b/src/java.compiler/share/classes/javax/lang/model/element/Parameterizable.java index 55d9042bca8dbe489334c0a872bff2db742667ea..cf0bbdfba37531a3a2f53716548c07c6bc1f1b70 100644 --- a/src/java.compiler/share/classes/javax/lang/model/element/Parameterizable.java +++ b/src/java.compiler/share/classes/javax/lang/model/element/Parameterizable.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2017, 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 @@ -30,7 +30,6 @@ import java.util.List; /** * A mixin interface for an element that has type parameters. * - * @author Joseph D. Darcy * @since 1.7 */ public interface Parameterizable extends Element { diff --git a/src/java.compiler/share/classes/javax/lang/model/element/QualifiedNameable.java b/src/java.compiler/share/classes/javax/lang/model/element/QualifiedNameable.java index fe7663aa578b1f082848c1400f76860064272eea..1b0316f893f51d3507fb50b5e508a68b8a92107b 100644 --- a/src/java.compiler/share/classes/javax/lang/model/element/QualifiedNameable.java +++ b/src/java.compiler/share/classes/javax/lang/model/element/QualifiedNameable.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2020, 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 @@ -28,7 +28,6 @@ package javax.lang.model.element; /** * A mixin interface for an element that has a qualified name. * - * @author Joseph D. Darcy * @since 1.7 */ public interface QualifiedNameable extends Element { diff --git a/src/java.compiler/share/classes/javax/lang/model/element/TypeElement.java b/src/java.compiler/share/classes/javax/lang/model/element/TypeElement.java index ab6221b06d363a3be0b2fe7daa9f4d414cb03811..4f2caafdfe8e71f84072c680ff3cb4f382cda4a0 100644 --- a/src/java.compiler/share/classes/javax/lang/model/element/TypeElement.java +++ b/src/java.compiler/share/classes/javax/lang/model/element/TypeElement.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2021, 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 @@ -53,9 +53,6 @@ import javax.lang.model.util.*; * source of information is Java source code, then the elements will be * returned in source code order. * - * @author Joseph D. Darcy - * @author Scott Seligman - * @author Peter von der Ahé * @see DeclaredType * @since 1.6 */ diff --git a/src/java.compiler/share/classes/javax/lang/model/element/TypeParameterElement.java b/src/java.compiler/share/classes/javax/lang/model/element/TypeParameterElement.java index bd8e0a3d1f6dc009e8e56db571b2f35b3204e3ff..cbaa8969126b4a0ce4a046fde589df9e2bb9c347 100644 --- a/src/java.compiler/share/classes/javax/lang/model/element/TypeParameterElement.java +++ b/src/java.compiler/share/classes/javax/lang/model/element/TypeParameterElement.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2020, 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 @@ -34,9 +34,6 @@ import javax.lang.model.type.TypeVariable; * or constructor element. * A type parameter declares a {@link TypeVariable}. * - * @author Joseph D. Darcy - * @author Scott Seligman - * @author Peter von der Ahé * @see TypeVariable * @since 1.6 */ diff --git a/src/java.compiler/share/classes/javax/lang/model/element/UnknownAnnotationValueException.java b/src/java.compiler/share/classes/javax/lang/model/element/UnknownAnnotationValueException.java index efe761ef1c6b9662820f5896653386d48cae1680..869235d88d3d02ffdc0fbb53c984b956006b6223 100644 --- a/src/java.compiler/share/classes/javax/lang/model/element/UnknownAnnotationValueException.java +++ b/src/java.compiler/share/classes/javax/lang/model/element/UnknownAnnotationValueException.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 @@ -35,9 +35,6 @@ import javax.lang.model.UnknownEntityException; * indicate that the visitor was created for a prior version of the * language. * - * @author Joseph D. Darcy - * @author Scott Seligman - * @author Peter von der Ahé * @see AnnotationValueVisitor#visitUnknown * @since 1.6 */ diff --git a/src/java.compiler/share/classes/javax/lang/model/element/UnknownDirectiveException.java b/src/java.compiler/share/classes/javax/lang/model/element/UnknownDirectiveException.java index 534183a3a933c37f63881ba84bd61484f83eebdc..7139573824af63080784bb886bf6203da3e5e661 100644 --- a/src/java.compiler/share/classes/javax/lang/model/element/UnknownDirectiveException.java +++ b/src/java.compiler/share/classes/javax/lang/model/element/UnknownDirectiveException.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2017, 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 @@ -34,9 +34,6 @@ import javax.lang.model.UnknownEntityException; * {@linkplain ModuleElement.DirectiveVisitor directive visitor} to * indicate that the visitor was created for a prior version of the language. * - * @author Joseph D. Darcy - * @author Scott Seligman - * @author Peter von der Ahé * @see ModuleElement.DirectiveVisitor#visitUnknown * @since 9 */ diff --git a/src/java.compiler/share/classes/javax/lang/model/element/UnknownElementException.java b/src/java.compiler/share/classes/javax/lang/model/element/UnknownElementException.java index 39779918c7167c6e1ce02ccdf1fab5d77dcac5e6..bb1f1d495b695dc0583e1448c3feae7a8f2598c4 100644 --- a/src/java.compiler/share/classes/javax/lang/model/element/UnknownElementException.java +++ b/src/java.compiler/share/classes/javax/lang/model/element/UnknownElementException.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 @@ -34,9 +34,6 @@ import javax.lang.model.UnknownEntityException; * {@linkplain ElementVisitor element visitor} to indicate that the * visitor was created for a prior version of the language. * - * @author Joseph D. Darcy - * @author Scott Seligman - * @author Peter von der Ahé * @see ElementVisitor#visitUnknown * @since 1.6 */ diff --git a/src/java.compiler/share/classes/javax/lang/model/element/VariableElement.java b/src/java.compiler/share/classes/javax/lang/model/element/VariableElement.java index ac7a949d9bbea3a0791002a26d167eeb8e59f258..a838aa383b7d161d24e7eed668a250a853a14c73 100644 --- a/src/java.compiler/share/classes/javax/lang/model/element/VariableElement.java +++ b/src/java.compiler/share/classes/javax/lang/model/element/VariableElement.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2020, 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 @@ -34,9 +34,6 @@ import javax.lang.model.type.TypeKind; * parameter, local variable, resource variable, or exception * parameter. * - * @author Joseph D. Darcy - * @author Scott Seligman - * @author Peter von der Ahé * @since 1.6 */ public interface VariableElement extends Element { diff --git a/src/java.compiler/share/classes/javax/lang/model/element/package-info.java b/src/java.compiler/share/classes/javax/lang/model/element/package-info.java index 38900425be96a00287952dc83465b69f54c3a660..aee2b235e79f41f86d01aaeb3dd95b65430d3324 100644 --- a/src/java.compiler/share/classes/javax/lang/model/element/package-info.java +++ b/src/java.compiler/share/classes/javax/lang/model/element/package-info.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2021, 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 @@ -107,9 +107,6 @@ *

    Unless otherwise specified, methods in this package will throw * a {@code NullPointerException} if given a {@code null} argument. * - * @author Joseph D. Darcy - * @author Scott Seligman - * @author Peter von der Ahé * @see javax.lang.model.util.Elements * @jls 6.1 Declarations * @jls 7.4 Package Declarations diff --git a/src/java.compiler/share/classes/javax/lang/model/package-info.java b/src/java.compiler/share/classes/javax/lang/model/package-info.java index fbdb003b1f2fcb987375fae28b00b812d8b0d5bc..65b0d407efb24b6cbd8c51f3fcfbc165e60b665b 100644 --- a/src/java.compiler/share/classes/javax/lang/model/package-info.java +++ b/src/java.compiler/share/classes/javax/lang/model/package-info.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 @@ -52,9 +52,6 @@ *

    Unless otherwise specified, methods in this package will throw * a {@code NullPointerException} if given a {@code null} argument. * - * @author Joseph D. Darcy - * @author Scott Seligman - * @author Peter von der Ahé * @since 1.6 */ diff --git a/src/java.compiler/share/classes/javax/lang/model/type/ArrayType.java b/src/java.compiler/share/classes/javax/lang/model/type/ArrayType.java index ac8c96c55f40ad959a900ab31a83bb5d0af36861..09e0de8b7e74dff08df6790b998acddc46cbb36d 100644 --- a/src/java.compiler/share/classes/javax/lang/model/type/ArrayType.java +++ b/src/java.compiler/share/classes/javax/lang/model/type/ArrayType.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2020, 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 @@ -31,9 +31,6 @@ package javax.lang.model.type; * A multidimensional array type is represented as an array type * whose component type is also an array type. * - * @author Joseph D. Darcy - * @author Scott Seligman - * @author Peter von der Ahé * @since 1.6 */ public interface ArrayType extends ReferenceType { diff --git a/src/java.compiler/share/classes/javax/lang/model/type/DeclaredType.java b/src/java.compiler/share/classes/javax/lang/model/type/DeclaredType.java index 3f6857049b820d13dd248a7336925479fe252f0e..ae799981a6af7ec68998a1e52f660b9cc89a1d2c 100644 --- a/src/java.compiler/share/classes/javax/lang/model/type/DeclaredType.java +++ b/src/java.compiler/share/classes/javax/lang/model/type/DeclaredType.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2020, 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 @@ -49,9 +49,6 @@ import javax.lang.model.util.Types; * Types#directSupertypes(TypeMirror)} method. This returns the * supertypes with any type arguments substituted in. * - * @author Joseph D. Darcy - * @author Scott Seligman - * @author Peter von der Ahé * @see TypeElement * @since 1.6 */ diff --git a/src/java.compiler/share/classes/javax/lang/model/type/ErrorType.java b/src/java.compiler/share/classes/javax/lang/model/type/ErrorType.java index 9d03ab93be987f09457822aa9f70632dffe07128..08654cdcb078d14333d8eef1d62b1f42ed4c00d7 100644 --- a/src/java.compiler/share/classes/javax/lang/model/type/ErrorType.java +++ b/src/java.compiler/share/classes/javax/lang/model/type/ErrorType.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2008, 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 @@ -33,9 +33,6 @@ package javax.lang.model.type; * information derived from such a type (such as its members or its * supertype) will not, in general, return meaningful results. * - * @author Joseph D. Darcy - * @author Scott Seligman - * @author Peter von der Ahé * @since 1.6 */ public interface ErrorType extends DeclaredType { diff --git a/src/java.compiler/share/classes/javax/lang/model/type/ExecutableType.java b/src/java.compiler/share/classes/javax/lang/model/type/ExecutableType.java index f711ebcb79b7ebca2e0def057bdebe959facb2f9..19953ff5e4a12d4e7be296b52e9e956158a3938f 100644 --- a/src/java.compiler/share/classes/javax/lang/model/type/ExecutableType.java +++ b/src/java.compiler/share/classes/javax/lang/model/type/ExecutableType.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2020, 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 @@ -41,9 +41,6 @@ import javax.lang.model.element.ExecutableElement; * type arguments are substituted into any types returned by the methods of * this interface. * - * @author Joseph D. Darcy - * @author Scott Seligman - * @author Peter von der Ahé * @see ExecutableElement * @since 1.6 */ diff --git a/src/java.compiler/share/classes/javax/lang/model/type/MirroredTypeException.java b/src/java.compiler/share/classes/javax/lang/model/type/MirroredTypeException.java index 21af5070a76aa2c9581bec8d13e3ede6ee94d50d..61117bc2cc6d0e1c14d6dba0054dd858b63a5169 100644 --- a/src/java.compiler/share/classes/javax/lang/model/type/MirroredTypeException.java +++ b/src/java.compiler/share/classes/javax/lang/model/type/MirroredTypeException.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2014, 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 @@ -34,9 +34,6 @@ import javax.lang.model.element.Element; * Thrown when an application attempts to access the {@link Class} object * corresponding to a {@link TypeMirror}. * - * @author Joseph D. Darcy - * @author Scott Seligman - * @author Peter von der Ahé * @see MirroredTypesException * @see Element#getAnnotation(Class) * @since 1.6 diff --git a/src/java.compiler/share/classes/javax/lang/model/type/MirroredTypesException.java b/src/java.compiler/share/classes/javax/lang/model/type/MirroredTypesException.java index 2cff3ffdaf6ec8bf703449f667c8e6d9f61b1aed..9fa3c5e8c3c01e3abe6e0d892c1325452ce985f8 100644 --- a/src/java.compiler/share/classes/javax/lang/model/type/MirroredTypesException.java +++ b/src/java.compiler/share/classes/javax/lang/model/type/MirroredTypesException.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2014, 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 @@ -37,9 +37,6 @@ import javax.lang.model.element.Element; * Thrown when an application attempts to access a sequence of {@link * Class} objects each corresponding to a {@link TypeMirror}. * - * @author Joseph D. Darcy - * @author Scott Seligman - * @author Peter von der Ahé * @see MirroredTypeException * @see Element#getAnnotation(Class) * @since 1.6 diff --git a/src/java.compiler/share/classes/javax/lang/model/type/NoType.java b/src/java.compiler/share/classes/javax/lang/model/type/NoType.java index 2be7e4b9b28ab6516c92fac0c3c7b142eb0a5256..84cb1297ef2c2353f9af0d139147bba7a2d7f003 100644 --- a/src/java.compiler/share/classes/javax/lang/model/type/NoType.java +++ b/src/java.compiler/share/classes/javax/lang/model/type/NoType.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2021, 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 @@ -40,9 +40,6 @@ import javax.lang.model.element.ExecutableElement; * of {@code java.lang.Object}. *

* - * @author Joseph D. Darcy - * @author Scott Seligman - * @author Peter von der Ahé * @see ExecutableElement#getReturnType() * @see javax.lang.model.util.Types#getNoType(TypeKind) * @since 1.6 diff --git a/src/java.compiler/share/classes/javax/lang/model/type/NullType.java b/src/java.compiler/share/classes/javax/lang/model/type/NullType.java index a846e07dc2e87f35cf779ef78f95243e3bd2b4c2..92feb514aab8c6cf9d4ed709342334cd9994536a 100644 --- a/src/java.compiler/share/classes/javax/lang/model/type/NullType.java +++ b/src/java.compiler/share/classes/javax/lang/model/type/NullType.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2021, 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 @@ -28,11 +28,8 @@ package javax.lang.model.type; /** * Represents the null type. - * This is the type of the expression {@code null}, + * This is the type of the expression {@code null}. * - * @author Joseph D. Darcy - * @author Scott Seligman - * @author Peter von der Ahé * @jls 3.10.7 The Null Literal * @jls 4.1 The Kinds of Types and Values * @see javax.lang.model.util.Types#getNullType() diff --git a/src/java.compiler/share/classes/javax/lang/model/type/PrimitiveType.java b/src/java.compiler/share/classes/javax/lang/model/type/PrimitiveType.java index 343f4b619900cb6d4d9008803ed5fece5149d05a..2772726113b6fdd8fcd075ae6f3845a6b122a30c 100644 --- a/src/java.compiler/share/classes/javax/lang/model/type/PrimitiveType.java +++ b/src/java.compiler/share/classes/javax/lang/model/type/PrimitiveType.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2021, 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 @@ -31,9 +31,6 @@ package javax.lang.model.type; * {@code boolean}, {@code byte}, {@code short}, {@code int}, * {@code long}, {@code char}, {@code float}, and {@code double}. * - * @author Joseph D. Darcy - * @author Scott Seligman - * @author Peter von der Ahé * @jls 4.2 Primitive Types and Values * @see javax.lang.model.util.Types#getPrimitiveType(TypeKind) * @since 1.6 diff --git a/src/java.compiler/share/classes/javax/lang/model/type/ReferenceType.java b/src/java.compiler/share/classes/javax/lang/model/type/ReferenceType.java index 9ab823ee81bbb17a488d4109c835a9c8dde46def..f9ce2dfcd6b311f29559f4f4596196b30d1a4fa0 100644 --- a/src/java.compiler/share/classes/javax/lang/model/type/ReferenceType.java +++ b/src/java.compiler/share/classes/javax/lang/model/type/ReferenceType.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2020, 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 @@ -31,9 +31,6 @@ package javax.lang.model.type; * These include class and interface types, array types, type variables, * and the null type. * - * @author Joseph D. Darcy - * @author Scott Seligman - * @author Peter von der Ahé * @jls 4.3 Reference Types and Values * @since 1.6 */ diff --git a/src/java.compiler/share/classes/javax/lang/model/type/TypeKind.java b/src/java.compiler/share/classes/javax/lang/model/type/TypeKind.java index cd6ece839393447a03c8d730543c70d00c9e7e65..5a6b8974ef8a63265181db45ce4671359de20861 100644 --- a/src/java.compiler/share/classes/javax/lang/model/type/TypeKind.java +++ b/src/java.compiler/share/classes/javax/lang/model/type/TypeKind.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2020, 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 @@ -33,9 +33,6 @@ package javax.lang.model.type; * accommodate new, currently unknown, language structures added to * future versions of the Java programming language. * - * @author Joseph D. Darcy - * @author Scott Seligman - * @author Peter von der Ahé * @see TypeMirror * @since 1.6 */ diff --git a/src/java.compiler/share/classes/javax/lang/model/type/TypeMirror.java b/src/java.compiler/share/classes/javax/lang/model/type/TypeMirror.java index 974f5439219cbdfe0efda3fd7e34a1f79714b059..a9a4613feb448f9c5fb06e19a2d7bc8b85f99458 100644 --- a/src/java.compiler/share/classes/javax/lang/model/type/TypeMirror.java +++ b/src/java.compiler/share/classes/javax/lang/model/type/TypeMirror.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2021, 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 @@ -50,9 +50,6 @@ import javax.lang.model.util.Types; * hierarchy since an implementation may choose to have a single * object implement multiple {@code TypeMirror} subinterfaces. * - * @author Joseph D. Darcy - * @author Scott Seligman - * @author Peter von der Ahé * @see Element * @see Types * @jls 4.1 The Kinds of Types and Values diff --git a/src/java.compiler/share/classes/javax/lang/model/type/TypeVariable.java b/src/java.compiler/share/classes/javax/lang/model/type/TypeVariable.java index fbb06d6693443a8100524a7a998059d63597cf18..e5ab0458f693a644cb75b3f8a2bb3da171e8ff90 100644 --- a/src/java.compiler/share/classes/javax/lang/model/type/TypeVariable.java +++ b/src/java.compiler/share/classes/javax/lang/model/type/TypeVariable.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2020, 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 @@ -41,9 +41,6 @@ import javax.lang.model.util.Types; * (see chapter {@jls 5} of * The Java Language Specification). * - * @author Joseph D. Darcy - * @author Scott Seligman - * @author Peter von der Ahé * @see TypeParameterElement * @jls 4.4 Type Variables * @since 1.6 diff --git a/src/java.compiler/share/classes/javax/lang/model/type/TypeVisitor.java b/src/java.compiler/share/classes/javax/lang/model/type/TypeVisitor.java index 7172c17a614117f4a6a3e2df968ec178df439c77..31d75fe7929405d4af675d59438abf19af93b49c 100644 --- a/src/java.compiler/share/classes/javax/lang/model/type/TypeVisitor.java +++ b/src/java.compiler/share/classes/javax/lang/model/type/TypeVisitor.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2020, 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 @@ -112,9 +112,6 @@ import javax.lang.model.util.*; * methods. Use {@code Void} for visitors that do not need an * additional parameter. * - * @author Joseph D. Darcy - * @author Scott Seligman - * @author Peter von der Ahé * @since 1.6 */ public interface TypeVisitor { diff --git a/src/java.compiler/share/classes/javax/lang/model/type/UnknownTypeException.java b/src/java.compiler/share/classes/javax/lang/model/type/UnknownTypeException.java index bd187d05145486a2f8139855a4632d750c682328..dac3fecf86c2b3aa0ae1b75af522396a57bee21b 100644 --- a/src/java.compiler/share/classes/javax/lang/model/type/UnknownTypeException.java +++ b/src/java.compiler/share/classes/javax/lang/model/type/UnknownTypeException.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 @@ -34,9 +34,6 @@ import javax.lang.model.UnknownEntityException; * TypeVisitor type visitor} to indicate that the visitor was created * for a prior version of the language. * - * @author Joseph D. Darcy - * @author Scott Seligman - * @author Peter von der Ahé * @see TypeVisitor#visitUnknown * @since 1.6 */ diff --git a/src/java.compiler/share/classes/javax/lang/model/type/WildcardType.java b/src/java.compiler/share/classes/javax/lang/model/type/WildcardType.java index ee1d0dac5553c1b19c2a3569ea320517dac6d170..1ac9e25ffb65047b21f90e3ef689ac7eaa26807b 100644 --- a/src/java.compiler/share/classes/javax/lang/model/type/WildcardType.java +++ b/src/java.compiler/share/classes/javax/lang/model/type/WildcardType.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2020, 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 @@ -38,9 +38,6 @@ package javax.lang.model.type; * {@code extends} clause, its lower bound explicitly set by a * {@code super} clause, or neither (but not both). * - * @author Joseph D. Darcy - * @author Scott Seligman - * @author Peter von der Ahé * @jls 4.5.1 Type Arguments of Parameterized Types * @since 1.6 */ diff --git a/src/java.compiler/share/classes/javax/lang/model/type/package-info.java b/src/java.compiler/share/classes/javax/lang/model/type/package-info.java index 13ec0f638bc9d7e8ffe07d5d8e863df0bb2ecd08..c5500d59ecb8ddc9a4eb4b1202e01be51e7df866 100644 --- a/src/java.compiler/share/classes/javax/lang/model/type/package-info.java +++ b/src/java.compiler/share/classes/javax/lang/model/type/package-info.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2020, 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 @@ -33,9 +33,6 @@ *

Unless otherwise specified, methods in this package will throw * a {@code NullPointerException} if given a {@code null} argument. * - * @author Joseph D. Darcy - * @author Scott Seligman - * @author Peter von der Ahé * @see javax.lang.model.util.Types * @jls 4.1 The Kinds of Types and Values * @jls 4.2 Primitive Types and Values diff --git a/src/java.compiler/share/classes/javax/lang/model/util/AbstractAnnotationValueVisitor6.java b/src/java.compiler/share/classes/javax/lang/model/util/AbstractAnnotationValueVisitor6.java index 0bf5674a6fb2de0c9dfb5db034584395a1aad28d..9d30df232121f9e88c9ee1f601e0632ba706baf1 100644 --- a/src/java.compiler/share/classes/javax/lang/model/util/AbstractAnnotationValueVisitor6.java +++ b/src/java.compiler/share/classes/javax/lang/model/util/AbstractAnnotationValueVisitor6.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2020, 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 @@ -60,10 +60,6 @@ import javax.annotation.processing.SupportedSourceVersion; * @param the return type of this visitor's methods * @param

the type of the additional parameter to this visitor's methods. * - * @author Joseph D. Darcy - * @author Scott Seligman - * @author Peter von der Ahé - * * @see AbstractAnnotationValueVisitor7 * @see AbstractAnnotationValueVisitor8 * @see AbstractAnnotationValueVisitor9 diff --git a/src/java.compiler/share/classes/javax/lang/model/util/AbstractElementVisitor6.java b/src/java.compiler/share/classes/javax/lang/model/util/AbstractElementVisitor6.java index 38adeb00b266a380f52dea912830dd0ab796e22c..943c16f4d6ca45b68c8f7410a291f878a6bc4b7a 100644 --- a/src/java.compiler/share/classes/javax/lang/model/util/AbstractElementVisitor6.java +++ b/src/java.compiler/share/classes/javax/lang/model/util/AbstractElementVisitor6.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2020, 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 @@ -62,10 +62,6 @@ import static javax.lang.model.SourceVersion.*; * methods. Use {@code Void} for visitors that do not need an * additional parameter. * - * @author Joseph D. Darcy - * @author Scott Seligman - * @author Peter von der Ahé - * * @see AbstractElementVisitor7 * @see AbstractElementVisitor8 * @see AbstractElementVisitor9 @@ -159,7 +155,6 @@ public abstract class AbstractElementVisitor6 implements ElementVisitor MODULE_KIND = Collections.unmodifiableSet(EnumSet.of(ElementKind.MODULE)); - @SuppressWarnings("preview") private static final Set TYPE_KINDS = Collections.unmodifiableSet(EnumSet.of(ElementKind.CLASS, ElementKind.ENUM, @@ -87,7 +82,6 @@ public class ElementFilter { ElementKind.RECORD, ElementKind.ANNOTATION_TYPE)); - @SuppressWarnings("preview") private static final Set RECORD_COMPONENT_KIND = Set.of(ElementKind.RECORD_COMPONENT); diff --git a/src/java.compiler/share/classes/javax/lang/model/util/ElementKindVisitor6.java b/src/java.compiler/share/classes/javax/lang/model/util/ElementKindVisitor6.java index 3d40feed86959e784bd2df82110a64fa6a3ac5eb..bdc4fe82ccf8f1a0f506167eee8afabda72f47d6 100644 --- a/src/java.compiler/share/classes/javax/lang/model/util/ElementKindVisitor6.java +++ b/src/java.compiler/share/classes/javax/lang/model/util/ElementKindVisitor6.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2020, 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 @@ -73,10 +73,6 @@ import javax.lang.model.SourceVersion; * methods. Use {@code Void} for visitors that do not need an * additional parameter. * - * @author Joseph D. Darcy - * @author Scott Seligman - * @author Peter von der Ahé - * * @see ElementKindVisitor7 * @see ElementKindVisitor8 * @see ElementKindVisitor9 @@ -139,7 +135,6 @@ public class ElementKindVisitor6 * @param p {@inheritDoc} * @return the result of the kind-specific visit method */ - @SuppressWarnings("preview") @Override public R visitType(TypeElement e, P p) { ElementKind k = e.getKind(); diff --git a/src/java.compiler/share/classes/javax/lang/model/util/ElementScanner6.java b/src/java.compiler/share/classes/javax/lang/model/util/ElementScanner6.java index f19fd5607722fc84b79fde3400f84559e99dc6a1..b13bd3cd0cc7c387096da22c3ecc6b6784f80be3 100644 --- a/src/java.compiler/share/classes/javax/lang/model/util/ElementScanner6.java +++ b/src/java.compiler/share/classes/javax/lang/model/util/ElementScanner6.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2020, 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 @@ -83,10 +83,6 @@ import static javax.lang.model.SourceVersion.*; * methods. Use {@code Void} for visitors that do not need an * additional parameter. * - * @author Joseph D. Darcy - * @author Scott Seligman - * @author Peter von der Ahé - * * @see ElementScanner7 * @see ElementScanner8 * @see ElementScanner9 diff --git a/src/java.compiler/share/classes/javax/lang/model/util/Elements.java b/src/java.compiler/share/classes/javax/lang/model/util/Elements.java index 03dec84feb195cfb24450d1866f970cd317d8dbf..6e3ea7a95e4dbb3368b7cc3039d47887800ab32b 100644 --- a/src/java.compiler/share/classes/javax/lang/model/util/Elements.java +++ b/src/java.compiler/share/classes/javax/lang/model/util/Elements.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2021, 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 @@ -42,9 +42,6 @@ import javax.lang.model.element.*; *

Compatibility Note: Methods may be added to this interface * in future releases of the platform. * - * @author Joseph D. Darcy - * @author Scott Seligman - * @author Peter von der Ahé * @see javax.annotation.processing.ProcessingEnvironment#getElementUtils * @since 1.6 */ diff --git a/src/java.compiler/share/classes/javax/lang/model/util/SimpleAnnotationValueVisitor6.java b/src/java.compiler/share/classes/javax/lang/model/util/SimpleAnnotationValueVisitor6.java index 64bbdda4fc44227a90856a3752217607c4978ff6..bf63d64f6b075cad90b2ac6df2bac4daf048ce23 100644 --- a/src/java.compiler/share/classes/javax/lang/model/util/SimpleAnnotationValueVisitor6.java +++ b/src/java.compiler/share/classes/javax/lang/model/util/SimpleAnnotationValueVisitor6.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2020, 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 @@ -67,10 +67,6 @@ import javax.annotation.processing.SupportedSourceVersion; * @param the return type of this visitor's methods * @param

the type of the additional parameter to this visitor's methods. * - * @author Joseph D. Darcy - * @author Scott Seligman - * @author Peter von der Ahé - * * @see SimpleAnnotationValueVisitor7 * @see SimpleAnnotationValueVisitor8 * @see SimpleAnnotationValueVisitor9 diff --git a/src/java.compiler/share/classes/javax/lang/model/util/SimpleElementVisitor6.java b/src/java.compiler/share/classes/javax/lang/model/util/SimpleElementVisitor6.java index 385ace89f5a2f2217836e8eeaeadf954e2c3271f..e894a0762957a5890c195745f35779d1823c930e 100644 --- a/src/java.compiler/share/classes/javax/lang/model/util/SimpleElementVisitor6.java +++ b/src/java.compiler/share/classes/javax/lang/model/util/SimpleElementVisitor6.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2020, 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 @@ -72,10 +72,6 @@ import static javax.lang.model.SourceVersion.*; * @param

the type of the additional parameter to this visitor's methods. Use {@code Void} * for visitors that do not need an additional parameter. * - * @author Joseph D. Darcy - * @author Scott Seligman - * @author Peter von der Ahé - * * @see SimpleElementVisitor7 * @see SimpleElementVisitor8 * @see SimpleElementVisitor9 diff --git a/src/java.compiler/share/classes/javax/lang/model/util/SimpleTypeVisitor6.java b/src/java.compiler/share/classes/javax/lang/model/util/SimpleTypeVisitor6.java index 38701ee71fdced3a8c9d68e0f1a20be71a61e58d..8e169094df26ace6a0502143b97b22aa8e79428e 100644 --- a/src/java.compiler/share/classes/javax/lang/model/util/SimpleTypeVisitor6.java +++ b/src/java.compiler/share/classes/javax/lang/model/util/SimpleTypeVisitor6.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2020, 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 @@ -72,10 +72,6 @@ import static javax.lang.model.SourceVersion.*; * methods. Use {@code Void} for visitors that do not need an * additional parameter. * - * @author Joseph D. Darcy - * @author Scott Seligman - * @author Peter von der Ahé - * * @see SimpleTypeVisitor7 * @see SimpleTypeVisitor8 * @see SimpleTypeVisitor9 diff --git a/src/java.compiler/share/classes/javax/lang/model/util/TypeKindVisitor6.java b/src/java.compiler/share/classes/javax/lang/model/util/TypeKindVisitor6.java index 661ecdd6e760093b696c2c0e70e3f1e7d8f5d576..602e89ae08b111473d77847476aeae072da0c77a 100644 --- a/src/java.compiler/share/classes/javax/lang/model/util/TypeKindVisitor6.java +++ b/src/java.compiler/share/classes/javax/lang/model/util/TypeKindVisitor6.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2020, 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 @@ -71,10 +71,6 @@ import static javax.lang.model.SourceVersion.*; * methods. Use {@code Void} for visitors that do not need an * additional parameter. * - * @author Joseph D. Darcy - * @author Scott Seligman - * @author Peter von der Ahé - * * @see TypeKindVisitor7 * @see TypeKindVisitor8 * @see TypeKindVisitor9 diff --git a/src/java.compiler/share/classes/javax/lang/model/util/Types.java b/src/java.compiler/share/classes/javax/lang/model/util/Types.java index cd1fe050ec5b42973a9e1b6df468ea58d1b0bde3..02c7085bd8cbad7e60e89940f4a0c5ffeb5bc60d 100644 --- a/src/java.compiler/share/classes/javax/lang/model/util/Types.java +++ b/src/java.compiler/share/classes/javax/lang/model/util/Types.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2020, 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 @@ -38,9 +38,6 @@ import javax.lang.model.type.*; *

Compatibility Note: Methods may be added to this interface * in future releases of the platform. * - * @author Joseph D. Darcy - * @author Scott Seligman - * @author Peter von der Ahé * @see javax.annotation.processing.ProcessingEnvironment#getTypeUtils * @since 1.6 */ diff --git a/src/java.compiler/share/classes/javax/lang/model/util/package-info.java b/src/java.compiler/share/classes/javax/lang/model/util/package-info.java index 97489de8f2f974ce7b2d3b05823091e20a5b1ef2..e6f34e6870ac4a63f88ba95e161e6803b72001a9 100644 --- a/src/java.compiler/share/classes/javax/lang/model/util/package-info.java +++ b/src/java.compiler/share/classes/javax/lang/model/util/package-info.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2006, 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 @@ -35,9 +35,6 @@ *

Unless otherwise specified, methods in this package will throw * a {@code NullPointerException} if given a {@code null} argument. * - * @author Joseph D. Darcy - * @author Scott Seligman - * @author Peter von der Ahé * @since 1.6 */ package javax.lang.model.util; diff --git a/src/java.compiler/share/classes/javax/tools/Diagnostic.java b/src/java.compiler/share/classes/javax/tools/Diagnostic.java index 8c3c2a34c8a3f819decff2116e0444c10882c59c..6ee666551f58adddde0bcd7d0c28b66997e1b0b1 100644 --- a/src/java.compiler/share/classes/javax/tools/Diagnostic.java +++ b/src/java.compiler/share/classes/javax/tools/Diagnostic.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2021, 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 @@ -41,8 +41,6 @@ import java.util.Locale; * * @param the type of source object used by this diagnostic * - * @author Peter von der Ahé - * @author Jonathan Gibbons * @since 1.6 */ public interface Diagnostic { diff --git a/src/java.compiler/share/classes/javax/tools/DiagnosticCollector.java b/src/java.compiler/share/classes/javax/tools/DiagnosticCollector.java index e1cfc33a3f763721d2de9765f932a7dd11834782..7e1ee34d3c8ae49480ca69a805ea628aad3fc1dd 100644 --- a/src/java.compiler/share/classes/javax/tools/DiagnosticCollector.java +++ b/src/java.compiler/share/classes/javax/tools/DiagnosticCollector.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, 2019, 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 @@ -36,7 +36,6 @@ import java.util.Objects; * @param the type of source objects used by diagnostics received * by this object * - * @author Peter von der Ahé * @since 1.6 */ public final class DiagnosticCollector implements DiagnosticListener { diff --git a/src/java.compiler/share/classes/javax/tools/DiagnosticListener.java b/src/java.compiler/share/classes/javax/tools/DiagnosticListener.java index 85a15dd225df7e33e03a415efa83ea2740df96be..6ed5191dd38defe10eda764591c044004a522831 100644 --- a/src/java.compiler/share/classes/javax/tools/DiagnosticListener.java +++ b/src/java.compiler/share/classes/javax/tools/DiagnosticListener.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2006, 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 @@ -31,8 +31,6 @@ package javax.tools; * @param the type of source objects used by diagnostics received * by this listener * - * @author Jonathan Gibbons - * @author Peter von der Ahé * @since 1.6 */ public interface DiagnosticListener { diff --git a/src/java.compiler/share/classes/javax/tools/FileObject.java b/src/java.compiler/share/classes/javax/tools/FileObject.java index 492ca6b3cc9c9bbf2055bdb5297581d5abd0e9f3..89a8499bf51bcbb4ac44379d269b55cbade5f95d 100644 --- a/src/java.compiler/share/classes/javax/tools/FileObject.java +++ b/src/java.compiler/share/classes/javax/tools/FileObject.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, 2014, 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 @@ -44,8 +44,6 @@ import java.net.URI; *

Unless explicitly allowed, all methods in this interface might * throw a NullPointerException if given a {@code null} argument. * - * @author Peter von der Ahé - * @author Jonathan Gibbons * @since 1.6 */ public interface FileObject { diff --git a/src/java.compiler/share/classes/javax/tools/ForwardingFileObject.java b/src/java.compiler/share/classes/javax/tools/ForwardingFileObject.java index 57bdb84000e95ccebc0200c122f4537507311721..98bb5a650a4062bcf41739356bfce5c2a30c9165 100644 --- a/src/java.compiler/share/classes/javax/tools/ForwardingFileObject.java +++ b/src/java.compiler/share/classes/javax/tools/ForwardingFileObject.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, 2020, 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 @@ -42,7 +42,6 @@ import java.util.Objects; * should be interpreted as referring indirectly to the {@link #fileObject delegate file object}. * * @param the kind of file object forwarded to by this object - * @author Peter von der Ahé * @since 1.6 */ public class ForwardingFileObject implements FileObject { diff --git a/src/java.compiler/share/classes/javax/tools/ForwardingJavaFileManager.java b/src/java.compiler/share/classes/javax/tools/ForwardingJavaFileManager.java index 9001b0ef38370b0f6f95b69de5624f2b199aad5d..e0bb999c05b7f4acd19938ad2760ec3b0fe7c169 100644 --- a/src/java.compiler/share/classes/javax/tools/ForwardingJavaFileManager.java +++ b/src/java.compiler/share/classes/javax/tools/ForwardingJavaFileManager.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2020, 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 @@ -42,7 +42,6 @@ import javax.tools.JavaFileObject.Kind; * should be interpreted as referring indirectly to the {@link #fileManager delegate file manager}. * * @param the kind of file manager forwarded to by this object - * @author Peter von der Ahé * @since 1.6 */ public class ForwardingJavaFileManager implements JavaFileManager { diff --git a/src/java.compiler/share/classes/javax/tools/ForwardingJavaFileObject.java b/src/java.compiler/share/classes/javax/tools/ForwardingJavaFileObject.java index 90f607cf3dc39881dab76377f418ab0257a108af..a940b23009d8e0874b815a2e7a8363f92c27e510 100644 --- a/src/java.compiler/share/classes/javax/tools/ForwardingJavaFileObject.java +++ b/src/java.compiler/share/classes/javax/tools/ForwardingJavaFileObject.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2020, 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 @@ -37,7 +37,6 @@ import javax.lang.model.element.NestingKind; * should be interpreted as referring indirectly to the {@link #fileObject delegate file object}. * * @param the kind of file object forwarded to by this object - * @author Peter von der Ahé * @since 1.6 */ public class ForwardingJavaFileObject diff --git a/src/java.compiler/share/classes/javax/tools/JavaCompiler.java b/src/java.compiler/share/classes/javax/tools/JavaCompiler.java index 9039490524ba1f691252cb311d11502795a7b3e8..7415a4d6fb92e45cb4107f7b6658f5645a530372 100644 --- a/src/java.compiler/share/classes/javax/tools/JavaCompiler.java +++ b/src/java.compiler/share/classes/javax/tools/JavaCompiler.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 @@ -190,8 +190,6 @@ import javax.annotation.processing.Processor; * * * - * @author Peter von der Ahé - * @author Jonathan Gibbons * @see DiagnosticListener * @see Diagnostic * @see JavaFileManager diff --git a/src/java.compiler/share/classes/javax/tools/JavaFileManager.java b/src/java.compiler/share/classes/javax/tools/JavaFileManager.java index 1fe510e809d2c11f2bcc414b461a0c94a457c2f6..524109bdf4dbf3147636cc506dcfc74b20488e1a 100644 --- a/src/java.compiler/share/classes/javax/tools/JavaFileManager.java +++ b/src/java.compiler/share/classes/javax/tools/JavaFileManager.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2021, 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 @@ -103,8 +103,6 @@ import static javax.tools.JavaFileObject.Kind; *

Unless explicitly allowed, all methods in this interface might * throw a NullPointerException if given a {@code null} argument. * - * @author Peter von der Ahé - * @author Jonathan Gibbons * @see JavaFileObject * @see FileObject * @since 1.6 diff --git a/src/java.compiler/share/classes/javax/tools/JavaFileObject.java b/src/java.compiler/share/classes/javax/tools/JavaFileObject.java index 48d6388df9e377d74602e816a75f343dbdb0e4be..0cac57a3176e427765f2a466fb041fd8c1bb0304 100644 --- a/src/java.compiler/share/classes/javax/tools/JavaFileObject.java +++ b/src/java.compiler/share/classes/javax/tools/JavaFileObject.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2020, 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 @@ -39,8 +39,6 @@ import java.util.Objects; *

Unless explicitly allowed, all methods in this interface might * throw a NullPointerException if given a {@code null} argument. * - * @author Peter von der Ahé - * @author Jonathan Gibbons * @see JavaFileManager * @since 1.6 */ diff --git a/src/java.compiler/share/classes/javax/tools/OptionChecker.java b/src/java.compiler/share/classes/javax/tools/OptionChecker.java index 653cf8fae244e903d10c9cb76f1abb5ea5423ff6..73c4311b44e49677d9170e3e603543f590a745a2 100644 --- a/src/java.compiler/share/classes/javax/tools/OptionChecker.java +++ b/src/java.compiler/share/classes/javax/tools/OptionChecker.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, 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 @@ -28,7 +28,6 @@ package javax.tools; /** * Interface for recognizing options. * - * @author Peter von der Ahé * @since 1.6 */ public interface OptionChecker { diff --git a/src/java.compiler/share/classes/javax/tools/SimpleJavaFileObject.java b/src/java.compiler/share/classes/javax/tools/SimpleJavaFileObject.java index 9c8d491996aacde4786c42297d5db0362b5ed1c9..b43bc4a60d8ce43b8fa8521b16e9747ed76e27c7 100644 --- a/src/java.compiler/share/classes/javax/tools/SimpleJavaFileObject.java +++ b/src/java.compiler/share/classes/javax/tools/SimpleJavaFileObject.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2020, 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 @@ -39,7 +39,6 @@ import javax.lang.model.element.NestingKind; * implementation and specification of any method of this class as * long as the general contract of JavaFileObject is obeyed. * - * @author Peter von der Ahé * @since 1.6 */ public class SimpleJavaFileObject implements JavaFileObject { diff --git a/src/java.compiler/share/classes/javax/tools/StandardJavaFileManager.java b/src/java.compiler/share/classes/javax/tools/StandardJavaFileManager.java index bd36f64be6f879d6eaa31fc8236f0f2bdf3203cd..769856535acee7aaf6b8a21ee99926864db0a01f 100644 --- a/src/java.compiler/share/classes/javax/tools/StandardJavaFileManager.java +++ b/src/java.compiler/share/classes/javax/tools/StandardJavaFileManager.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, 2020, 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 @@ -155,8 +155,6 @@ import java.util.List; * correct to call these methods with a single {@code Path} and have it be treated as * an {@code Iterable} of its components. * - * - * @author Peter von der Ahé * @since 1.6 */ public interface StandardJavaFileManager extends JavaFileManager { diff --git a/src/java.compiler/share/classes/javax/tools/StandardLocation.java b/src/java.compiler/share/classes/javax/tools/StandardLocation.java index afadab02f3d48f1dfae4eb3db56c2f6ef6aa1c95..2a9079f57245937ba814e93af8e90db068ee9c4d 100644 --- a/src/java.compiler/share/classes/javax/tools/StandardLocation.java +++ b/src/java.compiler/share/classes/javax/tools/StandardLocation.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, 2017, 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 @@ -32,7 +32,6 @@ import java.util.concurrent.*; /** * Standard locations of file objects. * - * @author Peter von der Ahé * @since 1.6 */ public enum StandardLocation implements Location { diff --git a/src/java.compiler/share/classes/javax/tools/Tool.java b/src/java.compiler/share/classes/javax/tools/Tool.java index cb9a79d16455312e99a05dc94c6b8379a5868dd5..62c7fdb06c969a01c73741ed5e28328a243f5be8 100644 --- a/src/java.compiler/share/classes/javax/tools/Tool.java +++ b/src/java.compiler/share/classes/javax/tools/Tool.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2014, 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 @@ -39,9 +39,6 @@ import javax.lang.model.SourceVersion; *

Tools can be located using {@link * java.util.ServiceLoader#load(Class)}. * - * @author Neal M Gafter - * @author Peter von der Ahé - * @author Jonathan Gibbons * @since 1.6 */ public interface Tool { diff --git a/src/java.compiler/share/classes/javax/tools/ToolProvider.java b/src/java.compiler/share/classes/javax/tools/ToolProvider.java index 3e2bff923905394faf59ef92a85798796ed49884..d05b65b0ffe94c7b0e756cc5bc8edd84d5e2a9e0 100644 --- a/src/java.compiler/share/classes/javax/tools/ToolProvider.java +++ b/src/java.compiler/share/classes/javax/tools/ToolProvider.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2021, 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,6 @@ import java.util.ServiceLoader; * providers of compilers. This class complements the * functionality of {@link java.util.ServiceLoader}. * - * @author Peter von der Ahé * @since 1.6 */ public class ToolProvider { diff --git a/src/java.compiler/share/classes/javax/tools/package-info.java b/src/java.compiler/share/classes/javax/tools/package-info.java index 963e6f2261c43a32a4f83689f215ecb49eff714b..6a7a3c3bb329628b0e273733d868f51f53cf854c 100644 --- a/src/java.compiler/share/classes/javax/tools/package-info.java +++ b/src/java.compiler/share/classes/javax/tools/package-info.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2020, 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 @@ -77,8 +77,6 @@ * JavaCompiler compiler = ServiceLoader.load(JavaCompiler.class).iterator().next(); * } * - * @author Peter von der Ahé - * @author Jonathan Gibbons * @since 1.6 */ package javax.tools; diff --git a/make/data/fontconfig/aix.fontconfig.properties b/src/java.desktop/aix/data/fontconfig/fontconfig.properties similarity index 100% rename from make/data/fontconfig/aix.fontconfig.properties rename to src/java.desktop/aix/data/fontconfig/fontconfig.properties diff --git a/make/data/fontconfig/bsd.fontconfig.properties b/src/java.desktop/bsd/data/fontconfig/fontconfig.properties similarity index 100% rename from make/data/fontconfig/bsd.fontconfig.properties rename to src/java.desktop/bsd/data/fontconfig/fontconfig.properties diff --git a/src/java.desktop/macosx/classes/com/apple/laf/AquaButtonUI.java b/src/java.desktop/macosx/classes/com/apple/laf/AquaButtonUI.java index 38f409f81fd24c0bd1cf8fc875e6639d38e20512..1ed74c0d9b000b68efdf594b614efb014bf5fb56 100644 --- a/src/java.desktop/macosx/classes/com/apple/laf/AquaButtonUI.java +++ b/src/java.desktop/macosx/classes/com/apple/laf/AquaButtonUI.java @@ -305,7 +305,15 @@ public class AquaButtonUI extends BasicButtonUI implements Sizeable { } // performs icon and text rect calculations - final String text = layoutAndGetText(g, b, aquaBorder, i, viewRect, iconRect, textRect); + final String text; + final View v = (View)c.getClientProperty(BasicHTML.propertyKey); + if (v != null) { + // use zero insets for view since layout only handles text calculations + text = layoutAndGetText(g, b, aquaBorder, new Insets(0,0,0,0), + viewRect, iconRect, textRect); + } else { + text = layoutAndGetText(g, b, aquaBorder, i, viewRect, iconRect, textRect); + } // Paint the Icon if (b.getIcon() != null) { @@ -317,7 +325,6 @@ public class AquaButtonUI extends BasicButtonUI implements Sizeable { } if (text != null && !text.isEmpty()) { - final View v = (View)c.getClientProperty(BasicHTML.propertyKey); if (v != null) { v.paint(g, textRect); } else { diff --git a/src/java.desktop/macosx/classes/sun/lwawt/macosx/CTextPipe.java b/src/java.desktop/macosx/classes/sun/lwawt/macosx/CTextPipe.java index f4dcc7ec675353aafc8464b44464b8ca7886d0e3..6aa36453ac0f9a6124dadf314689cdeab4c7cf12 100644 --- a/src/java.desktop/macosx/classes/sun/lwawt/macosx/CTextPipe.java +++ b/src/java.desktop/macosx/classes/sun/lwawt/macosx/CTextPipe.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 @@ -81,10 +81,57 @@ public class CTextPipe implements TextPipe { } } - public void drawGlyphVector(final SunGraphics2D sg2d, final GlyphVector gV, final float x, final float y) { - final Font prevFont = sg2d.getFont(); - sg2d.setFont(gV.getFont()); + private boolean hasSlotData(GlyphVector gv) { + final int length = gv.getNumGlyphs(); + for (int i = 0; i < length; i++) { + if ((gv.getGlyphCode(i) & CompositeGlyphMapper.SLOTMASK) != 0) { + return true; + } + } + return false; + } + + private Font getSlotFont(Font font, int slot) { + Font2D f2d = FontUtilities.getFont2D(font); + if (f2d instanceof CFont) { + CompositeFont cf = ((CFont)f2d).getCompositeFont2D(); + PhysicalFont pf = cf.getSlotFont(slot); + Font f = new Font(pf.getFontName(null), + font.getStyle(), font.getSize()); + return f; + } + return null; + } + + private GlyphVector getGlyphVectorWithRange(final Font font, final GlyphVector gV, int start, int count) { + int[] glyphs = new int[count]; + for (int i = 0; i < count; i++) { + glyphs[i] = gV.getGlyphCode(start+i) & CompositeGlyphMapper.GLYPHMASK; + } + // Positions should be null to recalculate by native methods, + // if GV was segmented. + StandardGlyphVector sgv = new StandardGlyphVector(font, + gV.getFontRenderContext(), + glyphs, + null, // positions + null, // indices + gV.getLayoutFlags()); + return sgv; + } + + private int getLengthOfSameSlot(final GlyphVector gV, final int targetSlot, final int start, final int length) { + int count = 1; + for (; start + count < length; count++) { + int slot = (gV.getGlyphCode(start + count) & + CompositeGlyphMapper.SLOTMASK) >> 24; + if (targetSlot != slot) { + break; + } + } + return count; + } + private void drawGlyphVectorImpl(final SunGraphics2D sg2d, final GlyphVector gV, final float x, final float y) { final long nativeStrikePtr = getNativeStrikePtr(sg2d); if (OSXSurfaceData.IsSimpleColor(sg2d.paint) && nativeStrikePtr != 0) { final OSXSurfaceData surfaceData = (OSXSurfaceData)sg2d.getSurfaceData(); @@ -92,6 +139,31 @@ public class CTextPipe implements TextPipe { } else { drawGlyphVectorAsShape(sg2d, gV, x, y); } + } + + public void drawGlyphVector(final SunGraphics2D sg2d, final GlyphVector gV, final float x, final float y) { + final Font prevFont = sg2d.getFont(); + sg2d.setFont(gV.getFont()); + + if (hasSlotData(gV)) { + final int length = gV.getNumGlyphs(); + float[] positions = gV.getGlyphPositions(0, length, null); + int start = 0; + while (start < length) { + int slot = (gV.getGlyphCode(start) & + CompositeGlyphMapper.SLOTMASK) >> 24; + sg2d.setFont(getSlotFont(gV.getFont(), slot)); + int count = getLengthOfSameSlot(gV, slot, start, length); + GlyphVector rangeGV = getGlyphVectorWithRange(sg2d.getFont(), + gV, start, count); + drawGlyphVectorImpl(sg2d, rangeGV, + x + positions[start * 2], + y + positions[start * 2 + 1]); + start += count; + } + } else { + drawGlyphVectorImpl(sg2d, gV, x, y); + } sg2d.setFont(prevFont); } diff --git a/make/data/fontconfig/macosx.fontconfig.properties b/src/java.desktop/macosx/data/fontconfig/fontconfig.properties similarity index 100% rename from make/data/fontconfig/macosx.fontconfig.properties rename to src/java.desktop/macosx/data/fontconfig/fontconfig.properties diff --git a/make/data/macosxicons/JavaApp.icns b/src/java.desktop/macosx/data/macosxicons/JavaApp.icns similarity index 100% rename from make/data/macosxicons/JavaApp.icns rename to src/java.desktop/macosx/data/macosxicons/JavaApp.icns diff --git a/src/java.desktop/share/classes/java/awt/AWTEventMulticaster.java b/src/java.desktop/share/classes/java/awt/AWTEventMulticaster.java index a9f102643f4b91ad39ac3dc7048c7fb075eac0b8..b7584fc84ddb91d79a12bb133a8e550b64e0a7aa 100644 --- a/src/java.desktop/share/classes/java/awt/AWTEventMulticaster.java +++ b/src/java.desktop/share/classes/java/awt/AWTEventMulticaster.java @@ -1097,9 +1097,9 @@ public class AWTEventMulticaster implements * FooListeners by the specified multicast * listener, or an empty array if no such listeners have been * chained by the specified multicast listener - * @exception NullPointerException if the specified + * @throws NullPointerException if the specified * {@code listenertype} parameter is {@code null} - * @exception ClassCastException if {@code listenerType} + * @throws ClassCastException if {@code listenerType} * doesn't specify a class or interface that implements * {@code java.util.EventListener} * diff --git a/src/java.desktop/share/classes/java/awt/BorderLayout.java b/src/java.desktop/share/classes/java/awt/BorderLayout.java index 88edc23dec4fae6f6c959d0a02a4af686162ffe5..e3b92a7996ae75e4e5ec4be21dd8ee3b3ecfd92a 100644 --- a/src/java.desktop/share/classes/java/awt/BorderLayout.java +++ b/src/java.desktop/share/classes/java/awt/BorderLayout.java @@ -419,7 +419,7 @@ public class BorderLayout implements LayoutManager2, * @param constraints an object that specifies how and where * the component is added to the layout. * @see java.awt.Container#add(java.awt.Component, java.lang.Object) - * @exception IllegalArgumentException if the constraint object is not + * @throws IllegalArgumentException if the constraint object is not * a string, or if it not one of the five specified constants. * @since 1.1 */ @@ -514,7 +514,7 @@ public class BorderLayout implements LayoutManager2, * {@code LINE_START}, {@code LINE_END} * @return the component at the given location, or {@code null} if * the location is empty - * @exception IllegalArgumentException if the constraint object is + * @throws IllegalArgumentException if the constraint object is * not one of the nine specified constants * @see #addLayoutComponent(java.awt.Component, java.lang.Object) * @since 1.5 @@ -562,9 +562,9 @@ public class BorderLayout implements LayoutManager2, * {@code Container}'s component orientation. * @return the component at the given location, or {@code null} if * the location is empty - * @exception IllegalArgumentException if the constraint object is + * @throws IllegalArgumentException if the constraint object is * not one of the five specified constants - * @exception NullPointerException if the target parameter is null + * @throws NullPointerException if the target parameter is null * @see #addLayoutComponent(java.awt.Component, java.lang.Object) * @since 1.5 */ diff --git a/src/java.desktop/share/classes/java/awt/BufferCapabilities.java b/src/java.desktop/share/classes/java/awt/BufferCapabilities.java index 22df13cfb5072998e55129e0343ef4838f9f7ff1..6edeae843aa45f50186c1e9a48ce6d5d10fd4fa7 100644 --- a/src/java.desktop/share/classes/java/awt/BufferCapabilities.java +++ b/src/java.desktop/share/classes/java/awt/BufferCapabilities.java @@ -47,7 +47,7 @@ public class BufferCapabilities implements Cloneable { * cannot be {@code null} * @param flipContents the contents of the back buffer after page-flipping, * {@code null} if page flipping is not used (implies blitting) - * @exception IllegalArgumentException if frontCaps or backCaps are + * @throws IllegalArgumentException if frontCaps or backCaps are * {@code null} */ public BufferCapabilities(ImageCapabilities frontCaps, diff --git a/src/java.desktop/share/classes/java/awt/Button.java b/src/java.desktop/share/classes/java/awt/Button.java index 35acb8d292882f2dc5ba7229de975da7b9751aef..524008e401a6273dfab4fd582508419d21d7b2c8 100644 --- a/src/java.desktop/share/classes/java/awt/Button.java +++ b/src/java.desktop/share/classes/java/awt/Button.java @@ -140,7 +140,7 @@ public class Button extends Component implements Accessible { /** * Constructs a button with an empty string for its label. * - * @exception HeadlessException if GraphicsEnvironment.isHeadless() + * @throws HeadlessException if GraphicsEnvironment.isHeadless() * returns true * @see java.awt.GraphicsEnvironment#isHeadless */ @@ -153,7 +153,7 @@ public class Button extends Component implements Accessible { * * @param label a string label for the button, or * {@code null} for no label - * @exception HeadlessException if GraphicsEnvironment.isHeadless() + * @throws HeadlessException if GraphicsEnvironment.isHeadless() * returns true * @see java.awt.GraphicsEnvironment#isHeadless */ @@ -339,7 +339,7 @@ public class Button extends Component implements Accessible { * FooListeners on this button, * or an empty array if no such * listeners have been added - * @exception ClassCastException if {@code listenerType} + * @throws ClassCastException if {@code listenerType} * doesn't specify a class or interface that implements * {@code java.util.EventListener} * diff --git a/src/java.desktop/share/classes/java/awt/Canvas.java b/src/java.desktop/share/classes/java/awt/Canvas.java index 1ee5380c6df08be44d8fea8ff81cb8568ef26310..7d90e148b6c313a9be2d917f9075031e1284a171 100644 --- a/src/java.desktop/share/classes/java/awt/Canvas.java +++ b/src/java.desktop/share/classes/java/awt/Canvas.java @@ -166,8 +166,8 @@ public class Canvas extends Component implements Accessible { * Each time this method is called, * the existing buffer strategy for this component is discarded. * @param numBuffers number of buffers to create, including the front buffer - * @exception IllegalArgumentException if numBuffers is less than 1. - * @exception IllegalStateException if the component is not displayable + * @throws IllegalArgumentException if numBuffers is less than 1. + * @throws IllegalStateException if the component is not displayable * @see #isDisplayable * @see #getBufferStrategy * @since 1.4 @@ -187,11 +187,11 @@ public class Canvas extends Component implements Accessible { * @param numBuffers number of buffers to create * @param caps the required capabilities for creating the buffer strategy; * cannot be {@code null} - * @exception AWTException if the capabilities supplied could not be + * @throws AWTException if the capabilities supplied could not be * supported or met; this may happen, for example, if there is not enough * accelerated memory currently available, or if page flipping is specified * but not possible. - * @exception IllegalArgumentException if numBuffers is less than 1, or if + * @throws IllegalArgumentException if numBuffers is less than 1, or if * caps is {@code null} * @see #getBufferStrategy * @since 1.4 diff --git a/src/java.desktop/share/classes/java/awt/CardLayout.java b/src/java.desktop/share/classes/java/awt/CardLayout.java index d53c86a9d454ab14e9a85849256d40373c8bf335..915376d032095727f5ff440706fdbd81b4152201 100644 --- a/src/java.desktop/share/classes/java/awt/CardLayout.java +++ b/src/java.desktop/share/classes/java/awt/CardLayout.java @@ -206,7 +206,7 @@ public class CardLayout implements LayoutManager2, * @param constraints a tag that identifies a particular * card in the layout. * @see java.awt.CardLayout#show(java.awt.Container, java.lang.String) - * @exception IllegalArgumentException if the constraint is not a string. + * @throws IllegalArgumentException if the constraint is not a string. */ public void addLayoutComponent(Component comp, Object constraints) { synchronized (comp.getTreeLock()) { diff --git a/src/java.desktop/share/classes/java/awt/Checkbox.java b/src/java.desktop/share/classes/java/awt/Checkbox.java index e72d249f8e31139b0903b5bb2aa1e99907600d7f..f4a642cb3297c13cd13a157058dc9f6c8bb8648b 100644 --- a/src/java.desktop/share/classes/java/awt/Checkbox.java +++ b/src/java.desktop/share/classes/java/awt/Checkbox.java @@ -146,7 +146,7 @@ public class Checkbox extends Component implements ItemSelectable, Accessible { * Creates a check box with an empty string for its label. * The state of this check box is set to "off," and it is not * part of any check box group. - * @exception HeadlessException if GraphicsEnvironment.isHeadless() + * @throws HeadlessException if GraphicsEnvironment.isHeadless() * returns true * @see java.awt.GraphicsEnvironment#isHeadless */ @@ -161,7 +161,7 @@ public class Checkbox extends Component implements ItemSelectable, Accessible { * * @param label a string label for this check box, * or {@code null} for no label. - * @exception HeadlessException if + * @throws HeadlessException if * {@code GraphicsEnvironment.isHeadless} * returns {@code true} * @see java.awt.GraphicsEnvironment#isHeadless @@ -178,7 +178,7 @@ public class Checkbox extends Component implements ItemSelectable, Accessible { * @param label a string label for this check box, * or {@code null} for no label * @param state the initial state of this check box - * @exception HeadlessException if + * @throws HeadlessException if * {@code GraphicsEnvironment.isHeadless} * returns {@code true} * @see java.awt.GraphicsEnvironment#isHeadless @@ -196,7 +196,7 @@ public class Checkbox extends Component implements ItemSelectable, Accessible { * @param state the initial state of this check box. * @param group a check box group for this check box, * or {@code null} for no group. - * @exception HeadlessException if + * @throws HeadlessException if * {@code GraphicsEnvironment.isHeadless} * returns {@code true} * @see java.awt.GraphicsEnvironment#isHeadless @@ -222,7 +222,7 @@ public class Checkbox extends Component implements ItemSelectable, Accessible { * @param group a check box group for this check box, * or {@code null} for no group. * @param state the initial state of this check box. - * @exception HeadlessException if + * @throws HeadlessException if * {@code GraphicsEnvironment.isHeadless} * returns {@code true} * @see java.awt.GraphicsEnvironment#isHeadless @@ -508,7 +508,7 @@ public class Checkbox extends Component implements ItemSelectable, Accessible { * FooListeners on this checkbox, * or an empty array if no such * listeners have been added - * @exception ClassCastException if {@code listenerType} + * @throws ClassCastException if {@code listenerType} * doesn't specify a class or interface that implements * {@code java.util.EventListener} * diff --git a/src/java.desktop/share/classes/java/awt/CheckboxMenuItem.java b/src/java.desktop/share/classes/java/awt/CheckboxMenuItem.java index 4df4ddbef856a39e7d23566383f4ce2322b4edbe..f95d1d39424a7894b528aa3868b655df84e43871 100644 --- a/src/java.desktop/share/classes/java/awt/CheckboxMenuItem.java +++ b/src/java.desktop/share/classes/java/awt/CheckboxMenuItem.java @@ -110,7 +110,7 @@ public class CheckboxMenuItem extends MenuItem implements ItemSelectable, Access /** * Create a check box menu item with an empty label. * The item's state is initially set to "off." - * @exception HeadlessException if GraphicsEnvironment.isHeadless() + * @throws HeadlessException if GraphicsEnvironment.isHeadless() * returns true * @see java.awt.GraphicsEnvironment#isHeadless * @since 1.1 @@ -125,7 +125,7 @@ public class CheckboxMenuItem extends MenuItem implements ItemSelectable, Access * @param label a string label for the check box menu item, * or {@code null} for an unlabeled menu item. - * @exception HeadlessException if GraphicsEnvironment.isHeadless() + * @throws HeadlessException if GraphicsEnvironment.isHeadless() * returns true * @see java.awt.GraphicsEnvironment#isHeadless */ @@ -140,7 +140,7 @@ public class CheckboxMenuItem extends MenuItem implements ItemSelectable, Access * @param state the initial state of the menu item, where * {@code true} indicates "on" and * {@code false} indicates "off." - * @exception HeadlessException if GraphicsEnvironment.isHeadless() + * @throws HeadlessException if GraphicsEnvironment.isHeadless() * returns true * @see java.awt.GraphicsEnvironment#isHeadless * @since 1.1 @@ -316,7 +316,7 @@ public class CheckboxMenuItem extends MenuItem implements ItemSelectable, Access * FooListeners on this checkbox menuitem, * or an empty array if no such * listeners have been added - * @exception ClassCastException if {@code listenerType} + * @throws ClassCastException if {@code listenerType} * doesn't specify a class or interface that implements * {@code java.util.EventListener} * diff --git a/src/java.desktop/share/classes/java/awt/Choice.java b/src/java.desktop/share/classes/java/awt/Choice.java index d8e8ab4c0267a44a96d98f0d7e4af6ddd3866e67..2b04239fd314c89a682d98675417b7efb3bdfa01 100644 --- a/src/java.desktop/share/classes/java/awt/Choice.java +++ b/src/java.desktop/share/classes/java/awt/Choice.java @@ -124,7 +124,7 @@ public class Choice extends Component implements ItemSelectable, Accessible { * By default, the first item added to the choice menu becomes the * selected item, until a different selection is made by the user * by calling one of the {@code select} methods. - * @exception HeadlessException if GraphicsEnvironment.isHeadless() + * @throws HeadlessException if GraphicsEnvironment.isHeadless() * returns true * @see java.awt.GraphicsEnvironment#isHeadless * @see #select(int) @@ -205,7 +205,7 @@ public class Choice extends Component implements ItemSelectable, Accessible { /** * Adds an item to this {@code Choice} menu. * @param item the item to be added - * @exception NullPointerException if the item's value is + * @throws NullPointerException if the item's value is * {@code null} * @since 1.1 */ @@ -219,7 +219,7 @@ public class Choice extends Component implements ItemSelectable, Accessible { *

* Adds an item to this {@code Choice} menu. * @param item the item to be added - * @exception NullPointerException if the item's value is equal to + * @throws NullPointerException if the item's value is equal to * {@code null} */ public void addItem(String item) { @@ -238,7 +238,7 @@ public class Choice extends Component implements ItemSelectable, Accessible { * invoking this method. * @param item the item to be added * @param index the new item position - * @exception NullPointerException if the item's value is equal to + * @throws NullPointerException if the item's value is equal to * {@code null} */ private void insertNoInvalidate(String item, int index) { @@ -274,7 +274,7 @@ public class Choice extends Component implements ItemSelectable, Accessible { * the selected item. * @param item the non-{@code null} item to be inserted * @param index the position at which the item should be inserted - * @exception IllegalArgumentException if index is less than 0 + * @throws IllegalArgumentException if index is less than 0 */ public void insert(String item, int index) { synchronized (this) { @@ -300,7 +300,7 @@ public class Choice extends Component implements ItemSelectable, Accessible { * item remains selected (and the selected index is * updated accordingly). * @param item the item to remove from this {@code Choice} menu - * @exception IllegalArgumentException if the item doesn't + * @throws IllegalArgumentException if the item doesn't * exist in the choice menu * @since 1.1 */ @@ -430,7 +430,7 @@ public class Choice extends Component implements ItemSelectable, Accessible { * {@code ItemEvent} is by user interaction. * * @param pos the position of the selected item - * @exception IllegalArgumentException if the specified + * @throws IllegalArgumentException if the specified * position is greater than the * number of items or less than zero * @see #getSelectedItem @@ -561,7 +561,7 @@ public class Choice extends Component implements ItemSelectable, Accessible { * FooListeners on this choice, * or an empty array if no such * listeners have been added - * @exception ClassCastException if {@code listenerType} + * @throws ClassCastException if {@code listenerType} * doesn't specify a class or interface that implements * {@code java.util.EventListener} * diff --git a/src/java.desktop/share/classes/java/awt/Color.java b/src/java.desktop/share/classes/java/awt/Color.java index aae90be8616dd0de749497032ef51dad7a4253ab..6bb4befd8e83c5eed52d4f98736c86d74c2b2109 100644 --- a/src/java.desktop/share/classes/java/awt/Color.java +++ b/src/java.desktop/share/classes/java/awt/Color.java @@ -722,7 +722,7 @@ public class Color implements Paint, java.io.Serializable { * an opaque color as a 24-bit integer * @return the new {@code Color} object. * @see java.lang.Integer#decode - * @exception NumberFormatException if the specified string cannot + * @throws NumberFormatException if the specified string cannot * be interpreted as a decimal, * octal, or hexadecimal integer. * @since 1.1 diff --git a/src/java.desktop/share/classes/java/awt/Component.java b/src/java.desktop/share/classes/java/awt/Component.java index 813f9bd0c796eea6b84f543004b91f85b48a52fc..cfd4cbe025a25632f2c17b8fa318a8c2bb542ec3 100644 --- a/src/java.desktop/share/classes/java/awt/Component.java +++ b/src/java.desktop/share/classes/java/awt/Component.java @@ -1420,7 +1420,7 @@ public abstract class Component implements ImageObserver, MenuContainer, * pointer. If the return value of this method is {@code null}, mouse * pointer is not directly above the {@code Component}. * - * @exception HeadlessException if GraphicsEnvironment.isHeadless() returns true + * @throws HeadlessException if GraphicsEnvironment.isHeadless() returns true * @see #isShowing * @see Container#getMousePosition * @return mouse coordinates relative to this {@code Component}, or null @@ -1984,7 +1984,7 @@ public abstract class Component implements ImageObserver, MenuContainer, * @return this component's locale; if this component does not * have a locale, the locale of its parent is returned * @see #setLocale - * @exception IllegalComponentStateException if the {@code Component} + * @throws IllegalComponentStateException if the {@code Component} * does not have its own locale and has not yet been added to * a containment hierarchy such that the locale can be determined * from the containing parent @@ -3827,8 +3827,8 @@ public abstract class Component implements ImageObserver, MenuContainer, * Each time this method is called, * the existing buffer strategy for this component is discarded. * @param numBuffers number of buffers to create, including the front buffer - * @exception IllegalArgumentException if numBuffers is less than 1. - * @exception IllegalStateException if the component is not displayable + * @throws IllegalArgumentException if numBuffers is less than 1. + * @throws IllegalStateException if the component is not displayable * @see #isDisplayable * @see Window#getBufferStrategy() * @see Canvas#getBufferStrategy() @@ -3884,11 +3884,11 @@ public abstract class Component implements ImageObserver, MenuContainer, * @param numBuffers number of buffers to create * @param caps the required capabilities for creating the buffer strategy; * cannot be {@code null} - * @exception AWTException if the capabilities supplied could not be + * @throws AWTException if the capabilities supplied could not be * supported or met; this may happen, for example, if there is not enough * accelerated memory currently available, or if page flipping is specified * but not possible. - * @exception IllegalArgumentException if numBuffers is less than 1, or if + * @throws IllegalArgumentException if numBuffers is less than 1, or if * caps is {@code null} * @see Window#getBufferStrategy() * @see Canvas#getBufferStrategy() @@ -4032,12 +4032,12 @@ public abstract class Component implements ImageObserver, MenuContainer, * @see Applet * @param numBuffers the number of buffers * @param caps the capabilities of the buffers - * @exception AWTException if the capabilities supplied could not be + * @throws AWTException if the capabilities supplied could not be * supported or met - * @exception ClassCastException if the component is not a canvas or + * @throws ClassCastException if the component is not a canvas or * window. - * @exception IllegalStateException if the component has no peer - * @exception IllegalArgumentException if {@code numBuffers} is less than two, + * @throws IllegalStateException if the component has no peer + * @throws IllegalArgumentException if {@code numBuffers} is less than two, * or if {@code BufferCapabilities.isPageFlipping} is not * {@code true}. * @see #createBuffers(int, BufferCapabilities) @@ -4066,10 +4066,10 @@ public abstract class Component implements ImageObserver, MenuContainer, * @param caps the capabilities of the buffers. * {@code BufferCapabilities.isPageFlipping} must be * {@code true}. - * @exception AWTException if the capabilities supplied could not be + * @throws AWTException if the capabilities supplied could not be * supported or met - * @exception IllegalStateException if the component has no peer - * @exception IllegalArgumentException if numBuffers is less than two, + * @throws IllegalStateException if the component has no peer + * @throws IllegalArgumentException if numBuffers is less than two, * or if {@code BufferCapabilities.isPageFlipping} is not * {@code true}. * @see java.awt.BufferCapabilities#isPageFlipping() @@ -4135,7 +4135,7 @@ public abstract class Component implements ImageObserver, MenuContainer, * Provides direct access to the back buffer as an image. * * @return the back buffer as an image - * @exception IllegalStateException if the buffers have not yet + * @throws IllegalStateException if the buffers have not yet * been created */ protected Image getBackBuffer() { @@ -4154,7 +4154,7 @@ public abstract class Component implements ImageObserver, MenuContainer, * for the contents of the back buffer. This should be one of the * values of the {@code BufferCapabilities.FlipContents} * property. - * @exception IllegalStateException if the buffers have not yet + * @throws IllegalStateException if the buffers have not yet * been created * @see java.awt.BufferCapabilities#getFlipContents() */ @@ -6060,7 +6060,7 @@ public abstract class Component implements ImageObserver, MenuContainer, * @return an array of all objects registered as * FooListeners on this component, * or an empty array if no such listeners have been added - * @exception ClassCastException if {@code listenerType} + * @throws ClassCastException if {@code listenerType} * doesn't specify a class or interface that implements * {@code java.util.EventListener} * @throws NullPointerException if {@code listenerType} is {@code null} @@ -8352,7 +8352,7 @@ public abstract class Component implements ImageObserver, MenuContainer, * Adds the specified popup menu to the component. * @param popup the popup menu to be added to the component. * @see #remove(MenuComponent) - * @exception NullPointerException if {@code popup} is {@code null} + * @throws NullPointerException if {@code popup} is {@code null} * @since 1.1 */ public void add(PopupMenu popup) { @@ -9192,7 +9192,7 @@ public abstract class Component implements ImageObserver, MenuContainer, * * @param orientation the new component orientation of this component and * the components contained within it. - * @exception NullPointerException if {@code orientation} is null. + * @throws NullPointerException if {@code orientation} is null. * @see #setComponentOrientation * @see #getComponentOrientation * @see #invalidate diff --git a/src/java.desktop/share/classes/java/awt/Container.java b/src/java.desktop/share/classes/java/awt/Container.java index 5b4489f3cac037367281592b11af7f29702c7b2c..f63c507a829abdcf04069e02d6bb9e4bba3de2c6 100644 --- a/src/java.desktop/share/classes/java/awt/Container.java +++ b/src/java.desktop/share/classes/java/awt/Container.java @@ -340,7 +340,7 @@ public class Container extends Component { * * @param n the index of the component to get. * @return the nth component in this container. - * @exception ArrayIndexOutOfBoundsException + * @throws ArrayIndexOutOfBoundsException * if the nth value does not exist. * @see Component#getTreeLock() */ @@ -429,7 +429,7 @@ public class Container extends Component { * display the added component. * * @param comp the component to be added - * @exception NullPointerException if {@code comp} is {@code null} + * @throws NullPointerException if {@code comp} is {@code null} * @see #addImpl * @see #invalidate * @see #validate @@ -456,7 +456,7 @@ public class Container extends Component { * @param name the name of the component to be added * @param comp the component to be added * @return the component added - * @exception NullPointerException if {@code comp} is {@code null} + * @throws NullPointerException if {@code comp} is {@code null} * @see #add(Component, Object) * @see #invalidate */ @@ -479,8 +479,8 @@ public class Container extends Component { * @param comp the component to be added * @param index the position at which to insert the component, * or {@code -1} to append the component to the end - * @exception NullPointerException if {@code comp} is {@code null} - * @exception IllegalArgumentException if {@code index} is invalid (see + * @throws NullPointerException if {@code comp} is {@code null} + * @throws IllegalArgumentException if {@code index} is invalid (see * {@link #addImpl} for details) * @return the component {@code comp} * @see #addImpl @@ -764,17 +764,17 @@ public class Container extends Component { * @param index the position in the container's list to * insert the component, where {@code getComponentCount()} * appends to the end - * @exception NullPointerException if {@code comp} is + * @throws NullPointerException if {@code comp} is * {@code null} - * @exception IllegalArgumentException if {@code comp} is one of the + * @throws IllegalArgumentException if {@code comp} is one of the * container's parents - * @exception IllegalArgumentException if {@code index} is not in + * @throws IllegalArgumentException if {@code index} is not in * the range {@code [0, getComponentCount()]} for moving * between containers, or not in the range * {@code [0, getComponentCount()-1]} for moving inside * a container - * @exception IllegalArgumentException if adding a container to itself - * @exception IllegalArgumentException if adding a {@code Window} + * @throws IllegalArgumentException if adding a container to itself + * @throws IllegalArgumentException if adding a {@code Window} * to a container * @see #getComponentZOrder(java.awt.Component) * @see #invalidate @@ -989,7 +989,7 @@ public class Container extends Component { * @param comp the component to be added * @param constraints an object expressing * layout constraints for this component - * @exception NullPointerException if {@code comp} is {@code null} + * @throws NullPointerException if {@code comp} is {@code null} * @see #addImpl * @see #invalidate * @see #validate @@ -1019,8 +1019,8 @@ public class Container extends Component { * @param index the position in the container's list at which to insert * the component; {@code -1} means insert at the end * component - * @exception NullPointerException if {@code comp} is {@code null} - * @exception IllegalArgumentException if {@code index} is invalid (see + * @throws NullPointerException if {@code comp} is {@code null} + * @throws IllegalArgumentException if {@code index} is invalid (see * {@link #addImpl} for details) * @see #addImpl * @see #invalidate @@ -1082,16 +1082,16 @@ public class Container extends Component { * @param index the position in the container's list at which to * insert the component, where {@code -1} * means append to the end - * @exception IllegalArgumentException if {@code index} is invalid; + * @throws IllegalArgumentException if {@code index} is invalid; * if {@code comp} is a child of this container, the valid * range is {@code [-1, getComponentCount()-1]}; if component is * not a child of this container, the valid range is * {@code [-1, getComponentCount()]} * - * @exception IllegalArgumentException if {@code comp} is an ancestor of + * @throws IllegalArgumentException if {@code comp} is an ancestor of * this container - * @exception IllegalArgumentException if adding a window to a container - * @exception NullPointerException if {@code comp} is {@code null} + * @throws IllegalArgumentException if adding a window to a container + * @throws NullPointerException if {@code comp} is {@code null} * @see #add(Component) * @see #add(Component, int) * @see #add(Component, java.lang.Object) @@ -2213,10 +2213,10 @@ public class Container extends Component { * @return an array of all objects registered as * FooListeners on this container, * or an empty array if no such listeners have been added - * @exception ClassCastException if {@code listenerType} + * @throws ClassCastException if {@code listenerType} * doesn't specify a class or interface that implements * {@code java.util.EventListener} - * @exception NullPointerException if {@code listenerType} is {@code null} + * @throws NullPointerException if {@code listenerType} is {@code null} * * @see #getContainerListeners * @@ -2622,7 +2622,7 @@ public class Container extends Component { * a non-null value if the mouse pointer is above {@code Container} or any * of its descendants. * - * @exception HeadlessException if GraphicsEnvironment.isHeadless() returns true + * @throws HeadlessException if GraphicsEnvironment.isHeadless() returns true * @param allowChildren true if children should be taken into account * @see Component#getMousePosition * @return mouse coordinates relative to this {@code Component}, or null @@ -3556,7 +3556,7 @@ public class Container extends Component { * * @param o the new component orientation of this container and * the components contained within it. - * @exception NullPointerException if {@code orientation} is null. + * @throws NullPointerException if {@code orientation} is null. * @see Component#setComponentOrientation * @see Component#getComponentOrientation * @see #invalidate diff --git a/src/java.desktop/share/classes/java/awt/Cursor.java b/src/java.desktop/share/classes/java/awt/Cursor.java index 936d17da46f6e2f8dc4f53485ddacbf51133f53c..cfccf06723becd6a24be72fb99cde1a7142ee1b8 100644 --- a/src/java.desktop/share/classes/java/awt/Cursor.java +++ b/src/java.desktop/share/classes/java/awt/Cursor.java @@ -285,9 +285,9 @@ public class Cursor implements java.io.Serializable { * * @param name a string describing the desired system-specific custom cursor * @return the system specific custom cursor named - * @exception HeadlessException if + * @throws HeadlessException if * {@code GraphicsEnvironment.isHeadless} returns true - * @exception AWTException in case of erroneous retrieving of the cursor + * @throws AWTException in case of erroneous retrieving of the cursor */ public static Cursor getSystemCustomCursor(final String name) throws AWTException, HeadlessException { diff --git a/src/java.desktop/share/classes/java/awt/Dialog.java b/src/java.desktop/share/classes/java/awt/Dialog.java index 1a54d70730697ca0aeff76ff75ea0f8c37ad9c1c..2c126e74ffc80b22fe657dbdac1c8b91b52af483 100644 --- a/src/java.desktop/share/classes/java/awt/Dialog.java +++ b/src/java.desktop/share/classes/java/awt/Dialog.java @@ -329,9 +329,9 @@ public class Dialog extends Window { * * @param owner the owner of the dialog or {@code null} if * this dialog has no owner - * @exception java.lang.IllegalArgumentException if the {@code owner}'s + * @throws java.lang.IllegalArgumentException if the {@code owner}'s * {@code GraphicsConfiguration} is not from a screen device - * @exception HeadlessException when + * @throws HeadlessException when * {@code GraphicsEnvironment.isHeadless()} returns {@code true} * * @see java.awt.GraphicsEnvironment#isHeadless @@ -352,9 +352,9 @@ public class Dialog extends Window { * windows when shown. If {@code false}, the dialog is {@code MODELESS}; * if {@code true}, the modality type property is set to * {@code DEFAULT_MODALITY_TYPE} - * @exception java.lang.IllegalArgumentException if the {@code owner}'s + * @throws java.lang.IllegalArgumentException if the {@code owner}'s * {@code GraphicsConfiguration} is not from a screen device - * @exception HeadlessException when + * @throws HeadlessException when * {@code GraphicsEnvironment.isHeadless()} returns {@code true} * * @see java.awt.Dialog.ModalityType @@ -376,9 +376,9 @@ public class Dialog extends Window { * this dialog has no owner * @param title the title of the dialog or {@code null} if this dialog * has no title - * @exception IllegalArgumentException if the {@code owner}'s + * @throws IllegalArgumentException if the {@code owner}'s * {@code GraphicsConfiguration} is not from a screen device - * @exception HeadlessException when + * @throws HeadlessException when * {@code GraphicsEnvironment.isHeadless()} returns {@code true} * * @see java.awt.GraphicsEnvironment#isHeadless @@ -401,9 +401,9 @@ public class Dialog extends Window { * windows when shown. If {@code false}, the dialog is {@code MODELESS}; * if {@code true}, the modality type property is set to * {@code DEFAULT_MODALITY_TYPE} - * @exception java.lang.IllegalArgumentException if the {@code owner}'s + * @throws java.lang.IllegalArgumentException if the {@code owner}'s * {@code GraphicsConfiguration} is not from a screen device - * @exception HeadlessException when + * @throws HeadlessException when * {@code GraphicsEnvironment.isHeadless()} returns {@code true} * * @see java.awt.Dialog.ModalityType @@ -433,9 +433,9 @@ public class Dialog extends Window { * @param gc the {@code GraphicsConfiguration} of the target screen device; * if {@code null}, the default system {@code GraphicsConfiguration} * is assumed - * @exception java.lang.IllegalArgumentException if {@code gc} + * @throws java.lang.IllegalArgumentException if {@code gc} * is not from a screen device - * @exception HeadlessException when + * @throws HeadlessException when * {@code GraphicsEnvironment.isHeadless()} returns {@code true} * * @see java.awt.Dialog.ModalityType @@ -459,9 +459,9 @@ public class Dialog extends Window { * * @param owner the owner of the dialog or {@code null} if this * dialog has no owner - * @exception java.lang.IllegalArgumentException if the {@code owner}'s + * @throws java.lang.IllegalArgumentException if the {@code owner}'s * {@code GraphicsConfiguration} is not from a screen device - * @exception HeadlessException when + * @throws HeadlessException when * {@code GraphicsEnvironment.isHeadless()} returns {@code true} * @see java.awt.GraphicsEnvironment#isHeadless * @since 1.2 @@ -478,9 +478,9 @@ public class Dialog extends Window { * has no owner * @param title the title of the dialog or {@code null} if this dialog * has no title - * @exception java.lang.IllegalArgumentException if the {@code owner}'s + * @throws java.lang.IllegalArgumentException if the {@code owner}'s * {@code GraphicsConfiguration} is not from a screen device - * @exception HeadlessException when + * @throws HeadlessException when * {@code GraphicsEnvironment.isHeadless()} returns {@code true} * * @see java.awt.GraphicsEnvironment#isHeadless @@ -502,9 +502,9 @@ public class Dialog extends Window { * windows when shown. If {@code false}, the dialog is {@code MODELESS}; * if {@code true}, the modality type property is set to * {@code DEFAULT_MODALITY_TYPE} - * @exception IllegalArgumentException if the {@code owner}'s + * @throws IllegalArgumentException if the {@code owner}'s * {@code GraphicsConfiguration} is not from a screen device - * @exception HeadlessException when + * @throws HeadlessException when * {@code GraphicsEnvironment.isHeadless()} returns {@code true} * * @see java.awt.Dialog.ModalityType @@ -536,9 +536,9 @@ public class Dialog extends Window { * @param gc the {@code GraphicsConfiguration} of the target screen device; * if {@code null}, the default system {@code GraphicsConfiguration} * is assumed - * @exception java.lang.IllegalArgumentException if {@code gc} + * @throws java.lang.IllegalArgumentException if {@code gc} * is not from a screen device - * @exception HeadlessException when + * @throws HeadlessException when * {@code GraphicsEnvironment.isHeadless()} returns {@code true} * * @see java.awt.Dialog.ModalityType @@ -565,12 +565,12 @@ public class Dialog extends Window { * {@link java.awt.Dialog Dialog}, {@link java.awt.Frame Frame}, any * of their descendants or {@code null} * - * @exception java.lang.IllegalArgumentException if the {@code owner} + * @throws java.lang.IllegalArgumentException if the {@code owner} * is not an instance of {@link java.awt.Dialog Dialog} or {@link * java.awt.Frame Frame} - * @exception java.lang.IllegalArgumentException if the {@code owner}'s + * @throws java.lang.IllegalArgumentException if the {@code owner}'s * {@code GraphicsConfiguration} is not from a screen device - * @exception HeadlessException when + * @throws HeadlessException when * {@code GraphicsEnvironment.isHeadless()} returns {@code true} * * @see java.awt.GraphicsEnvironment#isHeadless @@ -591,12 +591,12 @@ public class Dialog extends Window { * @param title the title of the dialog or {@code null} if this dialog * has no title * - * @exception java.lang.IllegalArgumentException if the {@code owner} + * @throws java.lang.IllegalArgumentException if the {@code owner} * is not an instance of {@link java.awt.Dialog Dialog} or {@link * java.awt.Frame Frame} - * @exception java.lang.IllegalArgumentException if the {@code owner}'s + * @throws java.lang.IllegalArgumentException if the {@code owner}'s * {@code GraphicsConfiguration} is not from a screen device - * @exception HeadlessException when + * @throws HeadlessException when * {@code GraphicsEnvironment.isHeadless()} returns {@code true} * * @see java.awt.GraphicsEnvironment#isHeadless @@ -618,14 +618,14 @@ public class Dialog extends Window { * windows when shown. {@code null} value and unsupported modality * types are equivalent to {@code MODELESS} * - * @exception java.lang.IllegalArgumentException if the {@code owner} + * @throws java.lang.IllegalArgumentException if the {@code owner} * is not an instance of {@link java.awt.Dialog Dialog} or {@link * java.awt.Frame Frame} - * @exception java.lang.IllegalArgumentException if the {@code owner}'s + * @throws java.lang.IllegalArgumentException if the {@code owner}'s * {@code GraphicsConfiguration} is not from a screen device - * @exception HeadlessException when + * @throws HeadlessException when * {@code GraphicsEnvironment.isHeadless()} returns {@code true} - * @exception SecurityException if the calling thread does not have permission + * @throws SecurityException if the calling thread does not have permission * to create modal dialogs with the given {@code modalityType} * * @see java.awt.Dialog.ModalityType @@ -653,14 +653,14 @@ public class Dialog extends Window { * windows when shown. {@code null} value and unsupported modality * types are equivalent to {@code MODELESS} * - * @exception java.lang.IllegalArgumentException if the {@code owner} + * @throws java.lang.IllegalArgumentException if the {@code owner} * is not an instance of {@link java.awt.Dialog Dialog} or {@link * java.awt.Frame Frame} - * @exception java.lang.IllegalArgumentException if the {@code owner}'s + * @throws java.lang.IllegalArgumentException if the {@code owner}'s * {@code GraphicsConfiguration} is not from a screen device - * @exception HeadlessException when + * @throws HeadlessException when * {@code GraphicsEnvironment.isHeadless()} returns {@code true} - * @exception SecurityException if the calling thread does not have permission + * @throws SecurityException if the calling thread does not have permission * to create modal dialogs with the given {@code modalityType} * * @see java.awt.Dialog.ModalityType @@ -704,14 +704,14 @@ public class Dialog extends Window { * if {@code null}, the default system {@code GraphicsConfiguration} * is assumed * - * @exception java.lang.IllegalArgumentException if the {@code owner} + * @throws java.lang.IllegalArgumentException if the {@code owner} * is not an instance of {@link java.awt.Dialog Dialog} or {@link * java.awt.Frame Frame} - * @exception java.lang.IllegalArgumentException if {@code gc} + * @throws java.lang.IllegalArgumentException if {@code gc} * is not from a screen device - * @exception HeadlessException when + * @throws HeadlessException when * {@code GraphicsEnvironment.isHeadless()} returns {@code true} - * @exception SecurityException if the calling thread does not have permission + * @throws SecurityException if the calling thread does not have permission * to create modal dialogs with the given {@code modalityType} * * @see java.awt.Dialog.ModalityType @@ -848,7 +848,7 @@ public class Dialog extends Window { * @param type specifies whether dialog blocks input to other * windows when shown. {@code null} value and unsupported modality * types are equivalent to {@code MODELESS} - * @exception SecurityException if the calling thread does not have permission + * @throws SecurityException if the calling thread does not have permission * to create modal dialogs with the given {@code modalityType} * * @see java.awt.Dialog#getModalityType diff --git a/src/java.desktop/share/classes/java/awt/EventQueue.java b/src/java.desktop/share/classes/java/awt/EventQueue.java index e7d1dcc82863c1c536ee3c5679f9486c73eefaec..4dce257f7278f47a563748d12dc14ab683457a74 100644 --- a/src/java.desktop/share/classes/java/awt/EventQueue.java +++ b/src/java.desktop/share/classes/java/awt/EventQueue.java @@ -544,7 +544,7 @@ public class EventQueue { * returns it. This method will block until an event has * been posted by another thread. * @return the next {@code AWTEvent} - * @exception InterruptedException + * @throws InterruptedException * if any thread has interrupted this thread */ public AWTEvent getNextEvent() throws InterruptedException { @@ -946,7 +946,7 @@ public class EventQueue { * Warning: To avoid deadlock, do not declare this method * synchronized in a subclass. * - * @exception EmptyStackException if no previous push was made + * @throws EmptyStackException if no previous push was made * on this {@code EventQueue} * @see java.awt.EventQueue#push * @since 1.2 @@ -1331,9 +1331,9 @@ public class EventQueue { * synchronously in the * {@link #isDispatchThread event dispatch thread} * of {@link Toolkit#getSystemEventQueue the system EventQueue} - * @exception InterruptedException if any thread has + * @throws InterruptedException if any thread has * interrupted this thread - * @exception InvocationTargetException if an throwable is thrown + * @throws InvocationTargetException if an throwable is thrown * when running {@code runnable} * @see #invokeLater * @see Toolkit#getSystemEventQueue diff --git a/src/java.desktop/share/classes/java/awt/FileDialog.java b/src/java.desktop/share/classes/java/awt/FileDialog.java index b6a501b44e96b7c73f690c063989b590b64a1d9a..399544b954789ccb0100be92e08542a177c51c6b 100644 --- a/src/java.desktop/share/classes/java/awt/FileDialog.java +++ b/src/java.desktop/share/classes/java/awt/FileDialog.java @@ -232,7 +232,7 @@ public class FileDialog extends Dialog { * @param title the title of the dialog * @param mode the mode of the dialog; either * {@code FileDialog.LOAD} or {@code FileDialog.SAVE} - * @exception IllegalArgumentException if an illegal file + * @throws IllegalArgumentException if an illegal file * dialog mode is supplied * @see java.awt.FileDialog#LOAD * @see java.awt.FileDialog#SAVE @@ -255,10 +255,10 @@ public class FileDialog extends Dialog { * displayed. * * @param parent the owner of the dialog - * @exception java.lang.IllegalArgumentException if the {@code parent}'s + * @throws java.lang.IllegalArgumentException if the {@code parent}'s * {@code GraphicsConfiguration} * is not from a screen device; - * @exception java.lang.IllegalArgumentException if {@code parent} + * @throws java.lang.IllegalArgumentException if {@code parent} * is {@code null}; this exception is always thrown when * {@code GraphicsEnvironment.isHeadless} * returns {@code true} @@ -285,10 +285,10 @@ public class FileDialog extends Dialog { * @param title the title of the dialog; a {@code null} value * will be accepted without causing a * {@code NullPointerException} to be thrown - * @exception java.lang.IllegalArgumentException if the {@code parent}'s + * @throws java.lang.IllegalArgumentException if the {@code parent}'s * {@code GraphicsConfiguration} * is not from a screen device; - * @exception java.lang.IllegalArgumentException if {@code parent} + * @throws java.lang.IllegalArgumentException if {@code parent} * is {@code null}; this exception is always thrown when * {@code GraphicsEnvironment.isHeadless} * returns {@code true} @@ -321,12 +321,12 @@ public class FileDialog extends Dialog { * {@code NullPointerException} to be thrown * @param mode the mode of the dialog; either * {@code FileDialog.LOAD} or {@code FileDialog.SAVE} - * @exception java.lang.IllegalArgumentException if an illegal + * @throws java.lang.IllegalArgumentException if an illegal * file dialog mode is supplied; - * @exception java.lang.IllegalArgumentException if the {@code parent}'s + * @throws java.lang.IllegalArgumentException if the {@code parent}'s * {@code GraphicsConfiguration} * is not from a screen device; - * @exception java.lang.IllegalArgumentException if {@code parent} + * @throws java.lang.IllegalArgumentException if {@code parent} * is {@code null}; this exception is always thrown when * {@code GraphicsEnvironment.isHeadless} * returns {@code true} @@ -408,7 +408,7 @@ public class FileDialog extends Dialog { * @see java.awt.FileDialog#LOAD * @see java.awt.FileDialog#SAVE * @see java.awt.FileDialog#getMode - * @exception IllegalArgumentException if an illegal file + * @throws IllegalArgumentException if an illegal file * dialog mode is supplied * @since 1.1 */ diff --git a/src/java.desktop/share/classes/java/awt/Frame.java b/src/java.desktop/share/classes/java/awt/Frame.java index 6dde9373c38714974047be58de9212643f82961f..e01ef082d4229865c0c964723719621ceb99f1cc 100644 --- a/src/java.desktop/share/classes/java/awt/Frame.java +++ b/src/java.desktop/share/classes/java/awt/Frame.java @@ -383,7 +383,7 @@ public class Frame extends Window implements MenuContainer { * Constructs a new instance of {@code Frame} that is * initially invisible. The title of the {@code Frame} * is empty. - * @exception HeadlessException when + * @throws HeadlessException when * {@code GraphicsEnvironment.isHeadless()} returns {@code true} * @see java.awt.GraphicsEnvironment#isHeadless() * @see Component#setSize @@ -401,9 +401,9 @@ public class Frame extends Window implements MenuContainer { * of the target screen device. If {@code gc} * is {@code null}, the system default * {@code GraphicsConfiguration} is assumed. - * @exception IllegalArgumentException if + * @throws IllegalArgumentException if * {@code gc} is not from a screen device. - * @exception HeadlessException when + * @throws HeadlessException when * {@code GraphicsEnvironment.isHeadless()} returns {@code true} * @see java.awt.GraphicsEnvironment#isHeadless() * @since 1.3 @@ -418,7 +418,7 @@ public class Frame extends Window implements MenuContainer { * @param title the title to be displayed in the frame's border. * A {@code null} value * is treated as an empty string, "". - * @exception HeadlessException when + * @throws HeadlessException when * {@code GraphicsEnvironment.isHeadless()} returns {@code true} * @see java.awt.GraphicsEnvironment#isHeadless() * @see java.awt.Component#setSize @@ -440,9 +440,9 @@ public class Frame extends Window implements MenuContainer { * of the target screen device. If {@code gc} is * {@code null}, the system default * {@code GraphicsConfiguration} is assumed. - * @exception IllegalArgumentException if {@code gc} + * @throws IllegalArgumentException if {@code gc} * is not from a screen device. - * @exception HeadlessException when + * @throws HeadlessException when * {@code GraphicsEnvironment.isHeadless()} returns {@code true} * @see java.awt.GraphicsEnvironment#isHeadless() * @see java.awt.Component#setSize diff --git a/src/java.desktop/share/classes/java/awt/GraphicsConfiguration.java b/src/java.desktop/share/classes/java/awt/GraphicsConfiguration.java index b698f0f3706d1e08fd328073e4b7ced0f1c3a57f..58d502ac03f47f57a06db6eab39a36ae4c06d706 100644 --- a/src/java.desktop/share/classes/java/awt/GraphicsConfiguration.java +++ b/src/java.desktop/share/classes/java/awt/GraphicsConfiguration.java @@ -261,7 +261,7 @@ public abstract class GraphicsConfiguration { * @param width the width of the returned {@code VolatileImage} * @param height the height of the returned {@code VolatileImage} * @param caps the image capabilities - * @exception AWTException if the supplied image capabilities could not + * @throws AWTException if the supplied image capabilities could not * be met by this graphics configuration * @since 1.4 */ @@ -294,7 +294,7 @@ public abstract class GraphicsConfiguration { * @see Transparency#BITMASK * @see Transparency#TRANSLUCENT * @throws IllegalArgumentException if the transparency is not a valid value - * @exception AWTException if the supplied image capabilities could not + * @throws AWTException if the supplied image capabilities could not * be met by this graphics configuration * @see Component#createVolatileImage(int, int) * @since 1.5 diff --git a/src/java.desktop/share/classes/java/awt/GraphicsDevice.java b/src/java.desktop/share/classes/java/awt/GraphicsDevice.java index d878f610fca9a9d8bc1bcd9e29a81c21ea84254f..c08c5580ae73fc388bc8d67f8e90a697e37b3d86 100644 --- a/src/java.desktop/share/classes/java/awt/GraphicsDevice.java +++ b/src/java.desktop/share/classes/java/awt/GraphicsDevice.java @@ -418,10 +418,10 @@ public abstract class GraphicsDevice { * * * @param dm The new display mode of this graphics device. - * @exception IllegalArgumentException if the {@code DisplayMode} + * @throws IllegalArgumentException if the {@code DisplayMode} * supplied is {@code null}, or is not available in the array returned * by {@code getDisplayModes} - * @exception UnsupportedOperationException if + * @throws UnsupportedOperationException if * {@code isDisplayChangeSupported} returns {@code false} * @see #getDisplayMode * @see #getDisplayModes diff --git a/src/java.desktop/share/classes/java/awt/GraphicsEnvironment.java b/src/java.desktop/share/classes/java/awt/GraphicsEnvironment.java index 438f9f399a0471c2c57d4b11090d212fcf943ad7..79102059b0ef782bf30290a7be8d3af8c25a9593 100644 --- a/src/java.desktop/share/classes/java/awt/GraphicsEnvironment.java +++ b/src/java.desktop/share/classes/java/awt/GraphicsEnvironment.java @@ -191,7 +191,7 @@ public abstract class GraphicsEnvironment { * objects. * @return an array containing all the {@code GraphicsDevice} * objects that represent screen devices - * @exception HeadlessException if isHeadless() returns true + * @throws HeadlessException if isHeadless() returns true * @see #isHeadless() */ public abstract GraphicsDevice[] getScreenDevices() @@ -201,7 +201,7 @@ public abstract class GraphicsEnvironment { * Returns the default screen {@code GraphicsDevice}. * @return the {@code GraphicsDevice} that represents the * default screen device - * @exception HeadlessException if isHeadless() returns true + * @throws HeadlessException if isHeadless() returns true * @see #isHeadless() */ public abstract GraphicsDevice getDefaultScreenDevice() @@ -383,7 +383,7 @@ public abstract class GraphicsEnvironment { * within the available display area using getMaximumWindowBounds(). * @return the point where Windows should be centered * - * @exception HeadlessException if isHeadless() returns true + * @throws HeadlessException if isHeadless() returns true * @see #getMaximumWindowBounds * @since 1.4 */ @@ -409,7 +409,7 @@ public abstract class GraphicsEnvironment { * {@code Toolkit.getScreenInsets()}. * @return the maximum bounds for centered Windows * - * @exception HeadlessException if isHeadless() returns true + * @throws HeadlessException if isHeadless() returns true * @see #getCenterPoint * @see GraphicsConfiguration#getBounds * @see Toolkit#getScreenInsets diff --git a/src/java.desktop/share/classes/java/awt/GridBagLayout.java b/src/java.desktop/share/classes/java/awt/GridBagLayout.java index ff3bec8b1153e36fe2db7d0021452ce0354f3c17..e0692ac0624bb5990201b4fd8745f0973b24c101 100644 --- a/src/java.desktop/share/classes/java/awt/GridBagLayout.java +++ b/src/java.desktop/share/classes/java/awt/GridBagLayout.java @@ -688,7 +688,7 @@ java.io.Serializable { * @param comp the component to be added * @param constraints an object that determines how * the component is added to the layout - * @exception IllegalArgumentException if {@code constraints} + * @throws IllegalArgumentException if {@code constraints} * is not a {@code GridBagConstraint} */ public void addLayoutComponent(Component comp, Object constraints) { diff --git a/src/java.desktop/share/classes/java/awt/GridLayout.java b/src/java.desktop/share/classes/java/awt/GridLayout.java index 4a3b66f4332e86c243260761106a083200453d5e..5c9265bc91214d8d0ca2fa3b977741985dcc3cac 100644 --- a/src/java.desktop/share/classes/java/awt/GridLayout.java +++ b/src/java.desktop/share/classes/java/awt/GridLayout.java @@ -186,7 +186,7 @@ public class GridLayout implements LayoutManager, java.io.Serializable { * any number of columns * @param hgap the horizontal gap * @param vgap the vertical gap - * @exception IllegalArgumentException if the value of both + * @throws IllegalArgumentException if the value of both * {@code rows} and {@code cols} is * set to zero */ @@ -212,7 +212,7 @@ public class GridLayout implements LayoutManager, java.io.Serializable { /** * Sets the number of rows in this layout to the specified value. * @param rows the number of rows in this layout - * @exception IllegalArgumentException if the value of both + * @throws IllegalArgumentException if the value of both * {@code rows} and {@code cols} is set to zero * @since 1.1 */ @@ -240,7 +240,7 @@ public class GridLayout implements LayoutManager, java.io.Serializable { * of columns displayed in the layout is determined by the total * number of components and the number of rows specified. * @param cols the number of columns in this layout - * @exception IllegalArgumentException if the value of both + * @throws IllegalArgumentException if the value of both * {@code rows} and {@code cols} is set to zero * @since 1.1 */ diff --git a/src/java.desktop/share/classes/java/awt/Image.java b/src/java.desktop/share/classes/java/awt/Image.java index 7e6273232694a0a3e6f5ecb14b6956316a81329d..1ad4ec9226f07c4549ea001fde8e02f4a31cf96f 100644 --- a/src/java.desktop/share/classes/java/awt/Image.java +++ b/src/java.desktop/share/classes/java/awt/Image.java @@ -105,7 +105,7 @@ public abstract class Image { * Creates a graphics context for drawing to an off-screen image. * This method can only be called for off-screen images. * @return a graphics context to draw to the off-screen image. - * @exception UnsupportedOperationException if called for a + * @throws UnsupportedOperationException if called for a * non-off-screen image. * @see java.awt.Graphics * @see java.awt.Component#createImage(int, int) @@ -162,7 +162,7 @@ public abstract class Image { * @param hints flags to indicate the type of algorithm to use * for image resampling. * @return a scaled version of the image. - * @exception IllegalArgumentException if {@code width} + * @throws IllegalArgumentException if {@code width} * or {@code height} is zero. * @see java.awt.Image#SCALE_DEFAULT * @see java.awt.Image#SCALE_FAST diff --git a/src/java.desktop/share/classes/java/awt/Label.java b/src/java.desktop/share/classes/java/awt/Label.java index b061efb51700631abef5c58954a7234bcbb1609d..ad8ff4c2b828c17c8bf93ec041ca5fd2a8ed7c28 100644 --- a/src/java.desktop/share/classes/java/awt/Label.java +++ b/src/java.desktop/share/classes/java/awt/Label.java @@ -114,7 +114,7 @@ public class Label extends Component implements Accessible { /** * Constructs an empty label. * The text of the label is the empty string {@code ""}. - * @exception HeadlessException if GraphicsEnvironment.isHeadless() + * @throws HeadlessException if GraphicsEnvironment.isHeadless() * returns true. * @see java.awt.GraphicsEnvironment#isHeadless */ @@ -129,7 +129,7 @@ public class Label extends Component implements Accessible { * A {@code null} value * will be accepted without causing a NullPointerException * to be thrown. - * @exception HeadlessException if GraphicsEnvironment.isHeadless() + * @throws HeadlessException if GraphicsEnvironment.isHeadless() * returns true. * @see java.awt.GraphicsEnvironment#isHeadless */ @@ -147,7 +147,7 @@ public class Label extends Component implements Accessible { * will be accepted without causing a NullPointerException * to be thrown. * @param alignment the alignment value. - * @exception HeadlessException if GraphicsEnvironment.isHeadless() + * @throws HeadlessException if GraphicsEnvironment.isHeadless() * returns true. * @see java.awt.GraphicsEnvironment#isHeadless */ @@ -216,7 +216,7 @@ public class Label extends Component implements Accessible { * Possible values are {@code Label.LEFT}, * {@code Label.RIGHT}, and {@code Label.CENTER}. * @param alignment the alignment to be set. - * @exception IllegalArgumentException if an improper value for + * @throws IllegalArgumentException if an improper value for * {@code alignment} is given. * @see java.awt.Label#getAlignment */ diff --git a/src/java.desktop/share/classes/java/awt/List.java b/src/java.desktop/share/classes/java/awt/List.java index f29374ab6bc062101dd13632dd42eeccaa246a82..fe1a5dc5530434058afe64baa62341928b30b851 100644 --- a/src/java.desktop/share/classes/java/awt/List.java +++ b/src/java.desktop/share/classes/java/awt/List.java @@ -193,7 +193,7 @@ public class List extends Component implements ItemSelectable, Accessible { * not allowed. Note that this is a convenience method for * {@code List(0, false)}. Also note that the number of visible * lines in the list cannot be changed after it has been created. - * @exception HeadlessException if GraphicsEnvironment.isHeadless() + * @throws HeadlessException if GraphicsEnvironment.isHeadless() * returns true. * @see java.awt.GraphicsEnvironment#isHeadless */ @@ -209,7 +209,7 @@ public class List extends Component implements ItemSelectable, Accessible { * of visible rows in the list cannot be changed after it has * been created. * @param rows the number of items to show. - * @exception HeadlessException if GraphicsEnvironment.isHeadless() + * @throws HeadlessException if GraphicsEnvironment.isHeadless() * returns true. * @see java.awt.GraphicsEnvironment#isHeadless * @since 1.1 @@ -238,7 +238,7 @@ public class List extends Component implements ItemSelectable, Accessible { * @param multipleMode if {@code true}, * then multiple selections are allowed; * otherwise, only one item can be selected at a time. - * @exception HeadlessException if GraphicsEnvironment.isHeadless() + * @throws HeadlessException if GraphicsEnvironment.isHeadless() * returns true. * @see java.awt.GraphicsEnvironment#isHeadless */ @@ -411,7 +411,7 @@ public class List extends Component implements ItemSelectable, Accessible { * with the new string. * @param newValue a new string to replace an existing item * @param index the position of the item to replace - * @exception ArrayIndexOutOfBoundsException if {@code index} + * @throws ArrayIndexOutOfBoundsException if {@code index} * is out of range */ public synchronized void replaceItem(String newValue, int index) { @@ -448,7 +448,7 @@ public class List extends Component implements ItemSelectable, Accessible { * If the specified item is selected, and is the only selected * item in the list, the list is set to have no selection. * @param item the item to remove from the list - * @exception IllegalArgumentException + * @throws IllegalArgumentException * if the item doesn't exist in the list * @since 1.1 */ @@ -470,7 +470,7 @@ public class List extends Component implements ItemSelectable, Accessible { * @param position the index of the item to delete * @see #add(String, int) * @since 1.1 - * @exception ArrayIndexOutOfBoundsException + * @throws ArrayIndexOutOfBoundsException * if the {@code position} is less than 0 or * greater than {@code getItemCount()-1} */ @@ -1053,7 +1053,7 @@ public class List extends Component implements ItemSelectable, Accessible { * FooListeners on this list, * or an empty array if no such * listeners have been added - * @exception ClassCastException if {@code listenerType} + * @throws ClassCastException if {@code listenerType} * doesn't specify a class or interface that implements * {@code java.util.EventListener} * @@ -1631,7 +1631,7 @@ public class List extends Component implements ItemSelectable, Accessible { * @return This component's locale. If this component does not have * a locale, the locale of its parent is returned. * - * @exception IllegalComponentStateException + * @throws IllegalComponentStateException * If the Component does not have its own locale and has not yet * been added to a containment hierarchy such that the locale can * be determined from the containing parent. diff --git a/src/java.desktop/share/classes/java/awt/MediaTracker.java b/src/java.desktop/share/classes/java/awt/MediaTracker.java index e2b754c40afd3b2c55469b7a8d6be8e74739ded3..37e372d0d1f6b521031f1090ff4e5ade3e8dbbc6 100644 --- a/src/java.desktop/share/classes/java/awt/MediaTracker.java +++ b/src/java.desktop/share/classes/java/awt/MediaTracker.java @@ -396,7 +396,7 @@ public class MediaTracker implements java.io.Serializable { * @see java.awt.MediaTracker#waitForAll(long) * @see java.awt.MediaTracker#isErrorAny * @see java.awt.MediaTracker#isErrorID - * @exception InterruptedException if any thread has + * @throws InterruptedException if any thread has * interrupted this thread */ public void waitForAll() throws InterruptedException { @@ -421,7 +421,7 @@ public class MediaTracker implements java.io.Serializable { * @see java.awt.MediaTracker#waitForAll(long) * @see java.awt.MediaTracker#isErrorAny * @see java.awt.MediaTracker#isErrorID - * @exception InterruptedException if any thread has + * @throws InterruptedException if any thread has * interrupted this thread. */ public synchronized boolean waitForAll(long ms) @@ -627,7 +627,7 @@ public class MediaTracker implements java.io.Serializable { * @see java.awt.MediaTracker#waitForAll * @see java.awt.MediaTracker#isErrorAny() * @see java.awt.MediaTracker#isErrorID(int) - * @exception InterruptedException if any thread has + * @throws InterruptedException if any thread has * interrupted this thread. */ public void waitForID(int id) throws InterruptedException { @@ -655,7 +655,7 @@ public class MediaTracker implements java.io.Serializable { * @see java.awt.MediaTracker#statusID * @see java.awt.MediaTracker#isErrorAny() * @see java.awt.MediaTracker#isErrorID(int) - * @exception InterruptedException if any thread has + * @throws InterruptedException if any thread has * interrupted this thread. */ public synchronized boolean waitForID(int id, long ms) diff --git a/src/java.desktop/share/classes/java/awt/Menu.java b/src/java.desktop/share/classes/java/awt/Menu.java index 5f24c7cb8bdd8e72965b41d1b1c0c0660e79b279..79c3dfe0d82dd6c417d76d76ae9aac0c9c9cad50 100644 --- a/src/java.desktop/share/classes/java/awt/Menu.java +++ b/src/java.desktop/share/classes/java/awt/Menu.java @@ -125,7 +125,7 @@ public class Menu extends MenuItem implements MenuContainer, Accessible { /** * Constructs a new menu with an empty label. This menu is not * a tear-off menu. - * @exception HeadlessException if GraphicsEnvironment.isHeadless() + * @throws HeadlessException if GraphicsEnvironment.isHeadless() * returns true. * @see java.awt.GraphicsEnvironment#isHeadless * @since 1.1 @@ -139,7 +139,7 @@ public class Menu extends MenuItem implements MenuContainer, Accessible { * a tear-off menu. * @param label the menu's label in the menu bar, or in * another menu of which this menu is a submenu. - * @exception HeadlessException if GraphicsEnvironment.isHeadless() + * @throws HeadlessException if GraphicsEnvironment.isHeadless() * returns true. * @see java.awt.GraphicsEnvironment#isHeadless */ @@ -158,7 +158,7 @@ public class Menu extends MenuItem implements MenuContainer, Accessible { * another menu of which this menu is a submenu. * @param tearOff if {@code true}, the menu * is a tear-off menu. - * @exception HeadlessException if GraphicsEnvironment.isHeadless() + * @throws HeadlessException if GraphicsEnvironment.isHeadless() * returns true. * @see java.awt.GraphicsEnvironment#isHeadless */ @@ -313,7 +313,7 @@ public class Menu extends MenuItem implements MenuContainer, Accessible { * item should be inserted. * @see java.awt.Menu#add(java.lang.String) * @see java.awt.Menu#add(java.awt.MenuItem) - * @exception IllegalArgumentException if the value of + * @throws IllegalArgumentException if the value of * {@code index} is less than zero * @since 1.1 */ @@ -357,7 +357,7 @@ public class Menu extends MenuItem implements MenuContainer, Accessible { * should be inserted * @see java.awt.Menu#add(java.lang.String) * @see java.awt.Menu#add(java.awt.MenuItem) - * @exception IllegalArgumentException if the value of + * @throws IllegalArgumentException if the value of * {@code index} is less than zero * @since 1.1 */ @@ -378,7 +378,7 @@ public class Menu extends MenuItem implements MenuContainer, Accessible { * Inserts a separator at the specified position. * @param index the position at which the * menu separator should be inserted. - * @exception IllegalArgumentException if the value of + * @throws IllegalArgumentException if the value of * {@code index} is less than 0. * @see java.awt.Menu#addSeparator * @since 1.1 diff --git a/src/java.desktop/share/classes/java/awt/MenuBar.java b/src/java.desktop/share/classes/java/awt/MenuBar.java index 2f78371407aa67869ba076feef67d778b8daa374..c1016f5bd0b2f15236438dcefcf05c24ea129046 100644 --- a/src/java.desktop/share/classes/java/awt/MenuBar.java +++ b/src/java.desktop/share/classes/java/awt/MenuBar.java @@ -127,7 +127,7 @@ public class MenuBar extends MenuComponent implements MenuContainer, Accessible /** * Creates a new menu bar. - * @exception HeadlessException if GraphicsEnvironment.isHeadless() + * @throws HeadlessException if GraphicsEnvironment.isHeadless() * returns true. * @see java.awt.GraphicsEnvironment#isHeadless */ diff --git a/src/java.desktop/share/classes/java/awt/MenuComponent.java b/src/java.desktop/share/classes/java/awt/MenuComponent.java index 2550eea7f520f3f4eab189678a4e594d248cf47b..a2d28fb9e3e3d606eeb306586d2b117616b42bdf 100644 --- a/src/java.desktop/share/classes/java/awt/MenuComponent.java +++ b/src/java.desktop/share/classes/java/awt/MenuComponent.java @@ -176,7 +176,7 @@ public abstract class MenuComponent implements java.io.Serializable { /** * Creates a {@code MenuComponent}. - * @exception HeadlessException if + * @throws HeadlessException if * {@code GraphicsEnvironment.isHeadless} * returns {@code true} * @see java.awt.GraphicsEnvironment#isHeadless diff --git a/src/java.desktop/share/classes/java/awt/MenuItem.java b/src/java.desktop/share/classes/java/awt/MenuItem.java index d1f6f59aa156bb4b8e8dd91af3ab53db11011fd6..adc37db7111a4c76fc0591ccccebe62677f5a84e 100644 --- a/src/java.desktop/share/classes/java/awt/MenuItem.java +++ b/src/java.desktop/share/classes/java/awt/MenuItem.java @@ -185,7 +185,7 @@ public class MenuItem extends MenuComponent implements Accessible { /** * Constructs a new MenuItem with an empty label and no keyboard * shortcut. - * @exception HeadlessException if GraphicsEnvironment.isHeadless() + * @throws HeadlessException if GraphicsEnvironment.isHeadless() * returns true. * @see java.awt.GraphicsEnvironment#isHeadless * @since 1.1 @@ -201,7 +201,7 @@ public class MenuItem extends MenuComponent implements Accessible { * menu items. By default, all menu items except for * separators are enabled. * @param label the label for this menu item. - * @exception HeadlessException if GraphicsEnvironment.isHeadless() + * @throws HeadlessException if GraphicsEnvironment.isHeadless() * returns true. * @see java.awt.GraphicsEnvironment#isHeadless * @since 1.0 @@ -218,7 +218,7 @@ public class MenuItem extends MenuComponent implements Accessible { * @param label the label for this menu item. * @param s the instance of {@code MenuShortcut} * associated with this menu item. - * @exception HeadlessException if GraphicsEnvironment.isHeadless() + * @throws HeadlessException if GraphicsEnvironment.isHeadless() * returns true. * @see java.awt.GraphicsEnvironment#isHeadless * @since 1.1 @@ -616,7 +616,7 @@ public class MenuItem extends MenuComponent implements Accessible { * FooListeners on this menu item, * or an empty array if no such * listeners have been added - * @exception ClassCastException if {@code listenerType} + * @throws ClassCastException if {@code listenerType} * doesn't specify a class or interface that implements * {@code java.util.EventListener} * diff --git a/src/java.desktop/share/classes/java/awt/MouseInfo.java b/src/java.desktop/share/classes/java/awt/MouseInfo.java index 76b5ed6e39747b28de073524f6fa325f359dcaf3..3dd115e0724f98719e910cfa96df52efb0fd0794 100644 --- a/src/java.desktop/share/classes/java/awt/MouseInfo.java +++ b/src/java.desktop/share/classes/java/awt/MouseInfo.java @@ -62,8 +62,8 @@ public class MouseInfo { * permission before creating and returning a {@code PointerInfo} * object. This may result in a {@code SecurityException}. * - * @exception HeadlessException if GraphicsEnvironment.isHeadless() returns true - * @exception SecurityException if a security manager exists and its + * @throws HeadlessException if GraphicsEnvironment.isHeadless() returns true + * @throws SecurityException if a security manager exists and its * {@code checkPermission} method doesn't allow the operation * @see GraphicsConfiguration * @see SecurityManager#checkPermission @@ -124,7 +124,7 @@ public class MouseInfo { * by requesting the {@code "awt.mouse.numButtons"} desktop property * which is set by the underlying native platform. * - * @exception HeadlessException if GraphicsEnvironment.isHeadless() returns true + * @throws HeadlessException if GraphicsEnvironment.isHeadless() returns true * @return number of buttons on the mouse * @see Toolkit#getDesktopProperty * @since 1.5 diff --git a/src/java.desktop/share/classes/java/awt/Polygon.java b/src/java.desktop/share/classes/java/awt/Polygon.java index 64f049cd1c7f7a95362c8c38c5bba02ea1dff420..e74ce5cb10faae4c97860a9495d15eb761e0fb1d 100644 --- a/src/java.desktop/share/classes/java/awt/Polygon.java +++ b/src/java.desktop/share/classes/java/awt/Polygon.java @@ -139,12 +139,12 @@ public class Polygon implements Shape, java.io.Serializable { * @param ypoints an array of Y coordinates * @param npoints the total number of points in the * {@code Polygon} - * @exception NegativeArraySizeException if the value of + * @throws NegativeArraySizeException if the value of * {@code npoints} is negative. - * @exception IndexOutOfBoundsException if {@code npoints} is + * @throws IndexOutOfBoundsException if {@code npoints} is * greater than the length of {@code xpoints} * or the length of {@code ypoints}. - * @exception NullPointerException if {@code xpoints} or + * @throws NullPointerException if {@code xpoints} or * {@code ypoints} is {@code null}. * @since 1.0 */ diff --git a/src/java.desktop/share/classes/java/awt/PopupMenu.java b/src/java.desktop/share/classes/java/awt/PopupMenu.java index fd56461df555ce617b7bfbea82c1cae85afe33d5..e9b88d2a12f4b2c4cf64b34b3cc0cd70243fa7d2 100644 --- a/src/java.desktop/share/classes/java/awt/PopupMenu.java +++ b/src/java.desktop/share/classes/java/awt/PopupMenu.java @@ -69,7 +69,7 @@ public class PopupMenu extends Menu { /** * Creates a new popup menu with an empty name. - * @exception HeadlessException if GraphicsEnvironment.isHeadless() + * @throws HeadlessException if GraphicsEnvironment.isHeadless() * returns true. * @see java.awt.GraphicsEnvironment#isHeadless */ @@ -82,7 +82,7 @@ public class PopupMenu extends Menu { * * @param label a non-{@code null} string specifying * the popup menu's label - * @exception HeadlessException if GraphicsEnvironment.isHeadless() + * @throws HeadlessException if GraphicsEnvironment.isHeadless() * returns true. * @see java.awt.GraphicsEnvironment#isHeadless */ @@ -149,12 +149,12 @@ public class PopupMenu extends Menu { * @param origin the component which defines the coordinate space * @param x the x coordinate position to popup the menu * @param y the y coordinate position to popup the menu - * @exception NullPointerException if the parent is {@code null} - * @exception IllegalArgumentException if this {@code PopupMenu} + * @throws NullPointerException if the parent is {@code null} + * @throws IllegalArgumentException if this {@code PopupMenu} * has a non-{@code Component} parent - * @exception IllegalArgumentException if the origin is not in the + * @throws IllegalArgumentException if the origin is not in the * parent's hierarchy - * @exception RuntimeException if the parent is not showing on screen + * @throws RuntimeException if the parent is not showing on screen */ @SuppressWarnings("deprecation") public void show(Component origin, int x, int y) { diff --git a/src/java.desktop/share/classes/java/awt/RenderingHints.java b/src/java.desktop/share/classes/java/awt/RenderingHints.java index d69ed339eee1cd108cca05bc2b3b589aeb33712b..46d2fda103198c9bac6138a6d4c1470f006078d1 100644 --- a/src/java.desktop/share/classes/java/awt/RenderingHints.java +++ b/src/java.desktop/share/classes/java/awt/RenderingHints.java @@ -1064,7 +1064,7 @@ public class RenderingHints * {@code RenderingHints} is to be tested. * @return {@code true} if this {@code RenderingHints} * contains a mapping for the specified key. - * @exception ClassCastException if the key can not + * @throws ClassCastException if the key can not * be cast to {@code RenderingHints.Key} */ public boolean containsKey(Object key) { @@ -1099,7 +1099,7 @@ public class RenderingHints * @return the value to which the key is mapped in this object or * {@code null} if the key is not mapped to any value in * this object. - * @exception ClassCastException if the key can not + * @throws ClassCastException if the key can not * be cast to {@code RenderingHints.Key} * @see #put(Object, Object) */ @@ -1117,11 +1117,11 @@ public class RenderingHints * @param value the rendering hint value. * @return the previous value of the specified key in this object * or {@code null} if it did not have one. - * @exception NullPointerException if the key is + * @throws NullPointerException if the key is * {@code null}. - * @exception ClassCastException if the key can not + * @throws ClassCastException if the key can not * be cast to {@code RenderingHints.Key} - * @exception IllegalArgumentException if the + * @throws IllegalArgumentException if the * {@link Key#isCompatibleValue(java.lang.Object) * Key.isCompatibleValue()} * method of the specified key returns false for the @@ -1163,7 +1163,7 @@ public class RenderingHints * {@code RenderingHints} object. This method does nothing if the * key is not in this {@code RenderingHints} object. * @param key the rendering hints key that needs to be removed - * @exception ClassCastException if the key can not + * @throws ClassCastException if the key can not * be cast to {@code RenderingHints.Key} * @return the value to which the key had previously been mapped in this * {@code RenderingHints} object, or {@code null} @@ -1179,10 +1179,10 @@ public class RenderingHints * any mappings that this {@code RenderingHints} had for any * of the keys currently in the specified {@code Map}. * @param m the specified {@code Map} - * @exception ClassCastException class of a key or value + * @throws ClassCastException class of a key or value * in the specified {@code Map} prevents it from being * stored in this {@code RenderingHints}. - * @exception IllegalArgumentException some aspect + * @throws IllegalArgumentException some aspect * of a key or value in the specified {@code Map} * prevents it from being stored in * this {@code RenderingHints}. diff --git a/src/java.desktop/share/classes/java/awt/Scrollbar.java b/src/java.desktop/share/classes/java/awt/Scrollbar.java index 34cd3ecc79934186f15fa998ac8895e2fa9352ad..c8f100cc1c28f35e4ffbe1d6898e754bf3a9db99 100644 --- a/src/java.desktop/share/classes/java/awt/Scrollbar.java +++ b/src/java.desktop/share/classes/java/awt/Scrollbar.java @@ -349,7 +349,7 @@ public class Scrollbar extends Component implements Adjustable, Accessible { * * * - * @exception HeadlessException if GraphicsEnvironment.isHeadless() + * @throws HeadlessException if GraphicsEnvironment.isHeadless() * returns true. * @see java.awt.GraphicsEnvironment#isHeadless */ @@ -366,9 +366,9 @@ public class Scrollbar extends Component implements Adjustable, Accessible { * indicating a horizontal or vertical scroll bar, respectively. * * @param orientation indicates the orientation of the scroll bar - * @exception IllegalArgumentException when an illegal value for + * @throws IllegalArgumentException when an illegal value for * the {@code orientation} argument is supplied - * @exception HeadlessException if GraphicsEnvironment.isHeadless() + * @throws HeadlessException if GraphicsEnvironment.isHeadless() * returns true. * @see java.awt.GraphicsEnvironment#isHeadless */ @@ -394,9 +394,9 @@ public class Scrollbar extends Component implements Adjustable, Accessible { * represented by the size of the bubble * @param minimum the minimum value of the scroll bar * @param maximum the maximum value of the scroll bar - * @exception IllegalArgumentException when an illegal value for + * @throws IllegalArgumentException when an illegal value for * the {@code orientation} argument is supplied - * @exception HeadlessException if GraphicsEnvironment.isHeadless() + * @throws HeadlessException if GraphicsEnvironment.isHeadless() * returns true. * @see #setValues * @see java.awt.GraphicsEnvironment#isHeadless @@ -457,7 +457,7 @@ public class Scrollbar extends Component implements Adjustable, Accessible { * {@code Scrollbar.HORIZONTAL} or * {@code Scrollbar.VERTICAL} * @see java.awt.Scrollbar#getOrientation - * @exception IllegalArgumentException if the value supplied + * @throws IllegalArgumentException if the value supplied * for {@code orientation} is not a * legal value * @since 1.1 @@ -1062,7 +1062,7 @@ public class Scrollbar extends Component implements Adjustable, Accessible { * @return an array of all objects registered as * FooListeners on this component, * or an empty array if no such listeners have been added - * @exception ClassCastException if {@code listenerType} + * @throws ClassCastException if {@code listenerType} * doesn't specify a class or interface that implements * {@code java.util.EventListener} * diff --git a/src/java.desktop/share/classes/java/awt/TextArea.java b/src/java.desktop/share/classes/java/awt/TextArea.java index 5e3e5ca6b331ae3ead354742bb8d7112cbd98aee..4c7baa52e4e767bdae7e7c681bd920329b8a74e7 100644 --- a/src/java.desktop/share/classes/java/awt/TextArea.java +++ b/src/java.desktop/share/classes/java/awt/TextArea.java @@ -157,7 +157,7 @@ public class TextArea extends TextComponent { * This text area is created with scrollbar visibility equal to * {@link #SCROLLBARS_BOTH}, so both vertical and horizontal * scrollbars will be visible for this text area. - * @exception HeadlessException if + * @throws HeadlessException if * {@code GraphicsEnvironment.isHeadless} returns true * @see java.awt.GraphicsEnvironment#isHeadless() */ @@ -173,7 +173,7 @@ public class TextArea extends TextComponent { * @param text the text to be displayed; if * {@code text} is {@code null}, the empty * string {@code ""} will be displayed - * @exception HeadlessException if + * @throws HeadlessException if * {@code GraphicsEnvironment.isHeadless} returns true * @see java.awt.GraphicsEnvironment#isHeadless() */ @@ -191,7 +191,7 @@ public class TextArea extends TextComponent { * text area. * @param rows the number of rows * @param columns the number of columns - * @exception HeadlessException if + * @throws HeadlessException if * {@code GraphicsEnvironment.isHeadless} returns true * @see java.awt.GraphicsEnvironment#isHeadless() */ @@ -212,7 +212,7 @@ public class TextArea extends TextComponent { * string {@code ""} will be displayed * @param rows the number of rows * @param columns the number of columns - * @exception HeadlessException if + * @throws HeadlessException if * {@code GraphicsEnvironment.isHeadless} returns true * @see java.awt.GraphicsEnvironment#isHeadless() */ @@ -252,7 +252,7 @@ public class TextArea extends TextComponent { * @param scrollbars a constant that determines what * scrollbars are created to view the text area * @since 1.1 - * @exception HeadlessException if + * @throws HeadlessException if * {@code GraphicsEnvironment.isHeadless} returns true * @see java.awt.GraphicsEnvironment#isHeadless() */ @@ -421,7 +421,7 @@ public class TextArea extends TextComponent { * @param rows the number of rows * @see #getRows() * @see #setColumns(int) - * @exception IllegalArgumentException if the value + * @throws IllegalArgumentException if the value * supplied for {@code rows} * is less than {@code 0} * @since 1.1 @@ -452,7 +452,7 @@ public class TextArea extends TextComponent { * @param columns the number of columns * @see #getColumns() * @see #setRows(int) - * @exception IllegalArgumentException if the value + * @throws IllegalArgumentException if the value * supplied for {@code columns} * is less than {@code 0} * @since 1.1 diff --git a/src/java.desktop/share/classes/java/awt/TextComponent.java b/src/java.desktop/share/classes/java/awt/TextComponent.java index 5dc8d4068cc7bfa0007fd7b0249abe0cf9c59240..b471b4e5ec6e8544b5a1296315a7b8485ccc5243 100644 --- a/src/java.desktop/share/classes/java/awt/TextComponent.java +++ b/src/java.desktop/share/classes/java/awt/TextComponent.java @@ -137,7 +137,7 @@ public class TextComponent extends Component implements Accessible { * @param text the text to be displayed; if * {@code text} is {@code null}, the empty * string {@code ""} will be displayed - * @exception HeadlessException if + * @throws HeadlessException if * {@code GraphicsEnvironment.isHeadless} * returns true * @see java.awt.GraphicsEnvironment#isHeadless @@ -511,7 +511,7 @@ public class TextComponent extends Component implements Accessible { * is thrown. * * @param position the position of the text insertion caret - * @exception IllegalArgumentException if {@code position} + * @throws IllegalArgumentException if {@code position} * is less than zero * @since 1.1 */ @@ -645,7 +645,7 @@ public class TextComponent extends Component implements Accessible { * FooListeners on this text component, * or an empty array if no such * listeners have been added - * @exception ClassCastException if {@code listenerType} + * @throws ClassCastException if {@code listenerType} * doesn't specify a class or interface that implements * {@code java.util.EventListener} * diff --git a/src/java.desktop/share/classes/java/awt/TextField.java b/src/java.desktop/share/classes/java/awt/TextField.java index 5ca720ee80ef95ecaf7826e06899da202f0eeee3..d2bfa0360b9bc80fb4a2531df3ef0f4ac553b302 100644 --- a/src/java.desktop/share/classes/java/awt/TextField.java +++ b/src/java.desktop/share/classes/java/awt/TextField.java @@ -152,7 +152,7 @@ public class TextField extends TextComponent { /** * Constructs a new text field. - * @exception HeadlessException if GraphicsEnvironment.isHeadless() + * @throws HeadlessException if GraphicsEnvironment.isHeadless() * returns true. * @see java.awt.GraphicsEnvironment#isHeadless */ @@ -167,7 +167,7 @@ public class TextField extends TextComponent { * string {@code ""} will be displayed. * If {@code text} contains EOL and/or LF characters, then * each will be replaced by space character. - * @exception HeadlessException if GraphicsEnvironment.isHeadless() + * @throws HeadlessException if GraphicsEnvironment.isHeadless() * returns true. * @see java.awt.GraphicsEnvironment#isHeadless */ @@ -182,7 +182,7 @@ public class TextField extends TextComponent { * @param columns the number of columns. If * {@code columns} is less than {@code 0}, * {@code columns} is set to {@code 0}. - * @exception HeadlessException if GraphicsEnvironment.isHeadless() + * @throws HeadlessException if GraphicsEnvironment.isHeadless() * returns true. * @see java.awt.GraphicsEnvironment#isHeadless */ @@ -203,7 +203,7 @@ public class TextField extends TextComponent { * @param columns the number of columns. If * {@code columns} is less than {@code 0}, * {@code columns} is set to {@code 0}. - * @exception HeadlessException if GraphicsEnvironment.isHeadless() + * @throws HeadlessException if GraphicsEnvironment.isHeadless() * returns true. * @see java.awt.GraphicsEnvironment#isHeadless */ @@ -369,7 +369,7 @@ public class TextField extends TextComponent { * approximate average character width that is platform-dependent. * @param columns the number of columns. * @see java.awt.TextField#getColumns - * @exception IllegalArgumentException if the value + * @throws IllegalArgumentException if the value * supplied for {@code columns} * is less than {@code 0}. * @since 1.1 @@ -585,7 +585,7 @@ public class TextField extends TextComponent { * FooListeners on this textfield, * or an empty array if no such * listeners have been added - * @exception ClassCastException if {@code listenerType} + * @throws ClassCastException if {@code listenerType} * doesn't specify a class or interface that implements * {@code java.util.EventListener} * diff --git a/src/java.desktop/share/classes/java/awt/Toolkit.java b/src/java.desktop/share/classes/java/awt/Toolkit.java index f3f4bcbb5c83041723e4d10ae329ab77dbcd2362..7399ced02bb463ebe410e5acbaa5dde65e98cc46 100644 --- a/src/java.desktop/share/classes/java/awt/Toolkit.java +++ b/src/java.desktop/share/classes/java/awt/Toolkit.java @@ -149,7 +149,7 @@ public abstract class Toolkit { * with the current system color values. * * @param systemColors an integer array. - * @exception HeadlessException if GraphicsEnvironment.isHeadless() + * @throws HeadlessException if GraphicsEnvironment.isHeadless() * returns true * @see java.awt.GraphicsEnvironment#isHeadless * @since 1.1 @@ -181,7 +181,7 @@ public abstract class Toolkit { * @param dynamic If true, Containers should re-layout their * components as the Container is being resized. If false, * the layout will be validated after resizing is completed. - * @exception HeadlessException if GraphicsEnvironment.isHeadless() + * @throws HeadlessException if GraphicsEnvironment.isHeadless() * returns true * @see #isDynamicLayoutSet() * @see #isDynamicLayoutActive() @@ -208,7 +208,7 @@ public abstract class Toolkit { * * @return true if validation of Containers is done dynamically, * false if validation is done after resizing is finished. - * @exception HeadlessException if GraphicsEnvironment.isHeadless() + * @throws HeadlessException if GraphicsEnvironment.isHeadless() * returns true * @see #setDynamicLayout(boolean dynamic) * @see #isDynamicLayoutActive() @@ -274,7 +274,7 @@ public abstract class Toolkit { * available from {@code GraphicsConfiguration} and * {@code GraphicsDevice}. * @return the size of this toolkit's screen, in pixels. - * @exception HeadlessException if GraphicsEnvironment.isHeadless() + * @throws HeadlessException if GraphicsEnvironment.isHeadless() * returns true * @see java.awt.GraphicsConfiguration#getBounds * @see java.awt.GraphicsDevice#getDisplayMode @@ -286,7 +286,7 @@ public abstract class Toolkit { /** * Returns the screen resolution in dots-per-inch. * @return this toolkit's screen resolution, in dots-per-inch. - * @exception HeadlessException if GraphicsEnvironment.isHeadless() + * @throws HeadlessException if GraphicsEnvironment.isHeadless() * returns true * @see java.awt.GraphicsEnvironment#isHeadless */ @@ -297,7 +297,7 @@ public abstract class Toolkit { * Gets the insets of the screen. * @param gc a {@code GraphicsConfiguration} * @return the insets of this toolkit's screen, in pixels. - * @exception HeadlessException if GraphicsEnvironment.isHeadless() + * @throws HeadlessException if GraphicsEnvironment.isHeadless() * returns true * @see java.awt.GraphicsEnvironment#isHeadless * @since 1.4 @@ -324,7 +324,7 @@ public abstract class Toolkit { * {@code getColorModel} method * of the {@code Component} class. * @return the color model of this toolkit's screen. - * @exception HeadlessException if GraphicsEnvironment.isHeadless() + * @throws HeadlessException if GraphicsEnvironment.isHeadless() * returns true * @see java.awt.GraphicsEnvironment#isHeadless * @see java.awt.image.ColorModel @@ -973,7 +973,7 @@ public abstract class Toolkit { * checkPermission} method to check {@code AWTPermission("accessClipboard")}. * * @return the system Clipboard - * @exception HeadlessException if GraphicsEnvironment.isHeadless() + * @throws HeadlessException if GraphicsEnvironment.isHeadless() * returns true * @see java.awt.GraphicsEnvironment#isHeadless * @see java.awt.datatransfer.Clipboard @@ -1020,7 +1020,7 @@ public abstract class Toolkit { * @return the system selection as a {@code Clipboard}, or * {@code null} if the native platform does not support a * system selection {@code Clipboard} - * @exception HeadlessException if GraphicsEnvironment.isHeadless() + * @throws HeadlessException if GraphicsEnvironment.isHeadless() * returns true * * @see java.awt.datatransfer.Clipboard @@ -1057,7 +1057,7 @@ public abstract class Toolkit { * Control key isn't the correct key for accelerators. * @return the modifier mask on the {@code Event} class * that is used for menu shortcuts on this toolkit. - * @exception HeadlessException if GraphicsEnvironment.isHeadless() + * @throws HeadlessException if GraphicsEnvironment.isHeadless() * returns true * @see java.awt.GraphicsEnvironment#isHeadless * @see java.awt.MenuBar @@ -1111,12 +1111,12 @@ public abstract class Toolkit { * @param keyCode the key code * @return {@code true} if the given key is currently in its "on" state; * otherwise {@code false} - * @exception java.lang.IllegalArgumentException if {@code keyCode} + * @throws java.lang.IllegalArgumentException if {@code keyCode} * is not one of the valid key codes - * @exception java.lang.UnsupportedOperationException if the host system doesn't + * @throws java.lang.UnsupportedOperationException if the host system doesn't * allow getting the state of this key programmatically, or if the keyboard * doesn't have this key - * @exception HeadlessException if GraphicsEnvironment.isHeadless() + * @throws HeadlessException if GraphicsEnvironment.isHeadless() * returns true * @see java.awt.GraphicsEnvironment#isHeadless * @since 1.3 @@ -1147,12 +1147,12 @@ public abstract class Toolkit { * * @param keyCode the key code * @param on the state of the key - * @exception java.lang.IllegalArgumentException if {@code keyCode} + * @throws java.lang.IllegalArgumentException if {@code keyCode} * is not one of the valid key codes - * @exception java.lang.UnsupportedOperationException if the host system doesn't + * @throws java.lang.UnsupportedOperationException if the host system doesn't * allow setting the state of this key programmatically, or if the keyboard * doesn't have this key - * @exception HeadlessException if GraphicsEnvironment.isHeadless() + * @throws HeadlessException if GraphicsEnvironment.isHeadless() * returns true * @see java.awt.GraphicsEnvironment#isHeadless * @since 1.3 @@ -1193,10 +1193,10 @@ public abstract class Toolkit { * hotSpot values must be less than the Dimension returned by * {@code getBestCursorSize} * @param name a localized description of the cursor, for Java Accessibility use - * @exception IndexOutOfBoundsException if the hotSpot values are outside + * @throws IndexOutOfBoundsException if the hotSpot values are outside * the bounds of the cursor * @return the cursor created - * @exception HeadlessException if GraphicsEnvironment.isHeadless() + * @throws HeadlessException if GraphicsEnvironment.isHeadless() * returns true * @see java.awt.GraphicsEnvironment#isHeadless * @since 1.2 @@ -1232,7 +1232,7 @@ public abstract class Toolkit { * to use. * @return the closest matching supported cursor size, or a dimension of 0,0 if * the Toolkit implementation doesn't support custom cursors. - * @exception HeadlessException if GraphicsEnvironment.isHeadless() + * @throws HeadlessException if GraphicsEnvironment.isHeadless() * returns true * @see java.awt.GraphicsEnvironment#isHeadless * @since 1.2 @@ -1262,7 +1262,7 @@ public abstract class Toolkit { * * @return the maximum number of colors, or zero if custom cursors are not * supported by this Toolkit implementation. - * @exception HeadlessException if GraphicsEnvironment.isHeadless() + * @throws HeadlessException if GraphicsEnvironment.isHeadless() * returns true * @see java.awt.GraphicsEnvironment#isHeadless * @since 1.2 @@ -1310,7 +1310,7 @@ public abstract class Toolkit { * @param state one of named frame state constants. * @return {@code true} is this frame state is supported by * this Toolkit implementation, {@code false} otherwise. - * @exception HeadlessException + * @throws HeadlessException * if {@code GraphicsEnvironment.isHeadless()} * returns {@code true}. * @see java.awt.Window#addWindowStateListener @@ -2203,7 +2203,7 @@ public abstract class Toolkit { * returned is unmodifiable. * @param highlight input method highlight * @return style attribute map, or {@code null} - * @exception HeadlessException if + * @throws HeadlessException if * {@code GraphicsEnvironment.isHeadless} returns true * @see java.awt.GraphicsEnvironment#isHeadless * @since 1.3 @@ -2360,7 +2360,7 @@ public abstract class Toolkit { * initialized with {@code true}. * Changing this value after the {@code Toolkit} class initialization will have no effect. * - * @exception HeadlessException if GraphicsEnvironment.isHeadless() returns true + * @throws HeadlessException if GraphicsEnvironment.isHeadless() returns true * @return {@code true} if events from extra mouse buttons are allowed to be processed and posted; * {@code false} otherwise * @see System#getProperty(String propertyName) diff --git a/src/java.desktop/share/classes/java/awt/Window.java b/src/java.desktop/share/classes/java/awt/Window.java index 59e63abbb3ca4d958027e0931ba4f9348858ec84..c58b2a5e94a3d0211a0e179bb56a72d3a40935e5 100644 --- a/src/java.desktop/share/classes/java/awt/Window.java +++ b/src/java.desktop/share/classes/java/awt/Window.java @@ -442,9 +442,9 @@ public class Window extends Container implements Accessible { * @param gc the {@code GraphicsConfiguration} of the target screen * device. If {@code gc} is {@code null}, the system default * {@code GraphicsConfiguration} is assumed - * @exception IllegalArgumentException if {@code gc} + * @throws IllegalArgumentException if {@code gc} * is not from a screen device - * @exception HeadlessException when + * @throws HeadlessException when * {@code GraphicsEnvironment.isHeadless()} returns {@code true} * * @see java.awt.GraphicsEnvironment#isHeadless @@ -544,7 +544,7 @@ public class Window extends Container implements Accessible { * If that check fails with a {@code SecurityException} then a warning * banner is created. * - * @exception HeadlessException when + * @throws HeadlessException when * {@code GraphicsEnvironment.isHeadless()} returns {@code true} * * @see java.awt.GraphicsEnvironment#isHeadless @@ -566,9 +566,9 @@ public class Window extends Container implements Accessible { * * @param owner the {@code Frame} to act as owner or {@code null} * if this window has no owner - * @exception IllegalArgumentException if the {@code owner}'s + * @throws IllegalArgumentException if the {@code owner}'s * {@code GraphicsConfiguration} is not from a screen device - * @exception HeadlessException when + * @throws HeadlessException when * {@code GraphicsEnvironment.isHeadless} returns {@code true} * * @see java.awt.GraphicsEnvironment#isHeadless @@ -593,9 +593,9 @@ public class Window extends Container implements Accessible { * * @param owner the {@code Window} to act as owner or * {@code null} if this window has no owner - * @exception IllegalArgumentException if the {@code owner}'s + * @throws IllegalArgumentException if the {@code owner}'s * {@code GraphicsConfiguration} is not from a screen device - * @exception HeadlessException when + * @throws HeadlessException when * {@code GraphicsEnvironment.isHeadless()} returns * {@code true} * @@ -627,9 +627,9 @@ public class Window extends Container implements Accessible { * @param gc the {@code GraphicsConfiguration} of the target * screen device; if {@code gc} is {@code null}, * the system default {@code GraphicsConfiguration} is assumed - * @exception IllegalArgumentException if {@code gc} + * @throws IllegalArgumentException if {@code gc} * is not from a screen device - * @exception HeadlessException when + * @throws HeadlessException when * {@code GraphicsEnvironment.isHeadless()} returns * {@code true} * @@ -1964,10 +1964,10 @@ public class Window extends Container implements Accessible { * FooListeners on this window, * or an empty array if no such * listeners have been added - * @exception ClassCastException if {@code listenerType} + * @throws ClassCastException if {@code listenerType} * doesn't specify a class or interface that implements * {@code java.util.EventListener} - * @exception NullPointerException if {@code listenerType} is {@code null} + * @throws NullPointerException if {@code listenerType} is {@code null} * * @see #getWindowListeners * @since 1.3 @@ -3372,8 +3372,8 @@ public class Window extends Container implements Accessible { * Each time this method is called, * the existing buffer strategy for this component is discarded. * @param numBuffers number of buffers to create - * @exception IllegalArgumentException if numBuffers is less than 1. - * @exception IllegalStateException if the component is not displayable + * @throws IllegalArgumentException if numBuffers is less than 1. + * @throws IllegalStateException if the component is not displayable * @see #isDisplayable * @see #getBufferStrategy * @since 1.4 @@ -3393,11 +3393,11 @@ public class Window extends Container implements Accessible { * @param numBuffers number of buffers to create, including the front buffer * @param caps the required capabilities for creating the buffer strategy; * cannot be {@code null} - * @exception AWTException if the capabilities supplied could not be + * @throws AWTException if the capabilities supplied could not be * supported or met; this may happen, for example, if there is not enough * accelerated memory currently available, or if page flipping is specified * but not possible. - * @exception IllegalArgumentException if numBuffers is less than 1, or if + * @throws IllegalArgumentException if numBuffers is less than 1, or if * caps is {@code null} * @see #getBufferStrategy * @since 1.4 diff --git a/src/java.desktop/share/classes/java/awt/dnd/DragSource.java b/src/java.desktop/share/classes/java/awt/dnd/DragSource.java index 8bbdfc24c06bf8cbc2ed114895ca3086dfaf946c..71bf6d27c8341b6974aa1e1f1bc9b438b91ebeb5 100644 --- a/src/java.desktop/share/classes/java/awt/dnd/DragSource.java +++ b/src/java.desktop/share/classes/java/awt/dnd/DragSource.java @@ -217,7 +217,7 @@ public class DragSource implements Serializable { * the underlying platform. * * @return the platform DragSource - * @exception HeadlessException if GraphicsEnvironment.isHeadless() + * @throws HeadlessException if GraphicsEnvironment.isHeadless() * returns true * @see java.awt.GraphicsEnvironment#isHeadless */ @@ -255,7 +255,7 @@ public class DragSource implements Serializable { /** * Creates a new {@code DragSource}. * - * @exception HeadlessException if GraphicsEnvironment.isHeadless() + * @throws HeadlessException if GraphicsEnvironment.isHeadless() * returns true * @see java.awt.GraphicsEnvironment#isHeadless */ @@ -682,7 +682,7 @@ public class DragSource implements Serializable { * FooListeners on this * {@code DragSource}, or an empty array if no such listeners * have been added - * @exception ClassCastException if {@code listenerType} + * @throws ClassCastException if {@code listenerType} * doesn't specify a class or interface that implements * {@code java.util.EventListener} * diff --git a/src/java.desktop/share/classes/java/awt/dnd/DropTarget.java b/src/java.desktop/share/classes/java/awt/dnd/DropTarget.java index 7ba9c9711da065fa8a1950c3663d0fd71bdfa921..fbd086792a5bff6d04010cabf08a4782d0b586c6 100644 --- a/src/java.desktop/share/classes/java/awt/dnd/DropTarget.java +++ b/src/java.desktop/share/classes/java/awt/dnd/DropTarget.java @@ -89,7 +89,7 @@ public class DropTarget implements DropTargetListener, Serializable { * @param dtl The {@code DropTargetListener} for this {@code DropTarget} * @param act Is the {@code DropTarget} accepting drops. * @param fm The {@code FlavorMap} to use, or null for the default {@code FlavorMap} - * @exception HeadlessException if GraphicsEnvironment.isHeadless() + * @throws HeadlessException if GraphicsEnvironment.isHeadless() * returns true * @see java.awt.GraphicsEnvironment#isHeadless */ @@ -136,7 +136,7 @@ public class DropTarget implements DropTargetListener, Serializable { * @param ops The default acceptable actions for this {@code DropTarget} * @param dtl The {@code DropTargetListener} for this {@code DropTarget} * @param act Is the {@code DropTarget} accepting drops. - * @exception HeadlessException if GraphicsEnvironment.isHeadless() + * @throws HeadlessException if GraphicsEnvironment.isHeadless() * returns true * @see java.awt.GraphicsEnvironment#isHeadless */ @@ -149,7 +149,7 @@ public class DropTarget implements DropTargetListener, Serializable { /** * Creates a {@code DropTarget}. - * @exception HeadlessException if GraphicsEnvironment.isHeadless() + * @throws HeadlessException if GraphicsEnvironment.isHeadless() * returns true * @see java.awt.GraphicsEnvironment#isHeadless */ @@ -165,7 +165,7 @@ public class DropTarget implements DropTargetListener, Serializable { * The Component will receive drops only if it is enabled. * @param c The {@code Component} with which this {@code DropTarget} is associated * @param dtl The {@code DropTargetListener} for this {@code DropTarget} - * @exception HeadlessException if GraphicsEnvironment.isHeadless() + * @throws HeadlessException if GraphicsEnvironment.isHeadless() * returns true * @see java.awt.GraphicsEnvironment#isHeadless */ @@ -185,7 +185,7 @@ public class DropTarget implements DropTargetListener, Serializable { * @param c The {@code Component} with which this {@code DropTarget} is associated * @param ops The default acceptable actions for this {@code DropTarget} * @param dtl The {@code DropTargetListener} for this {@code DropTarget} - * @exception HeadlessException if GraphicsEnvironment.isHeadless() + * @throws HeadlessException if GraphicsEnvironment.isHeadless() * returns true * @see java.awt.GraphicsEnvironment#isHeadless */ diff --git a/src/java.desktop/share/classes/java/awt/doc-files/Modality.html b/src/java.desktop/share/classes/java/awt/doc-files/Modality.html index eeb779672dc85a826481fed0fe507ecb4e2a54b7..e20d9175fb775a7f8303327cd994efe51bedc1fd 100644 --- a/src/java.desktop/share/classes/java/awt/doc-files/Modality.html +++ b/src/java.desktop/share/classes/java/awt/doc-files/Modality.html @@ -8,7 +8,7 @@ */ @Override - @ForceInline - public final + public abstract VectorMask test(VectorOperators.Test op, - VectorMask m) { - return test(op).and(m); + VectorMask m); + + /*package-private*/ + @ForceInline + final + > + M testTemplate(Class maskType, Test op, M mask) { + ByteSpecies vsp = vspecies(); + mask.check(maskType, this); + if (opKind(op, VO_SPECIAL)) { + VectorMask m = mask; + if (op == IS_DEFAULT) { + m = compare(EQ, (byte) 0, m); + } else if (op == IS_NEGATIVE) { + m = compare(LT, (byte) 0, m); + } + else { + throw new AssertionError(op); + } + return maskType.cast(m); + } + int opc = opCode(op); + throw new AssertionError(op); } /** @@ -4317,12 +4336,12 @@ public abstract class ByteVector extends AbstractVector { */ static ByteSpecies species(VectorShape s) { Objects.requireNonNull(s); - switch (s) { - case S_64_BIT: return (ByteSpecies) SPECIES_64; - case S_128_BIT: return (ByteSpecies) SPECIES_128; - case S_256_BIT: return (ByteSpecies) SPECIES_256; - case S_512_BIT: return (ByteSpecies) SPECIES_512; - case S_Max_BIT: return (ByteSpecies) SPECIES_MAX; + switch (s.switchKey) { + case VectorShape.SK_64_BIT: return (ByteSpecies) SPECIES_64; + case VectorShape.SK_128_BIT: return (ByteSpecies) SPECIES_128; + case VectorShape.SK_256_BIT: return (ByteSpecies) SPECIES_256; + case VectorShape.SK_512_BIT: return (ByteSpecies) SPECIES_512; + case VectorShape.SK_Max_BIT: return (ByteSpecies) SPECIES_MAX; default: throw new IllegalArgumentException("Bad shape: " + s); } } diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Double128Vector.java b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Double128Vector.java index d4762fe779659e522abb67ca10c604639c7cecb5..24c32c848c35489dfe9e6ebfaceba2167692a488 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Double128Vector.java +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Double128Vector.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 @@ -357,6 +357,12 @@ final class Double128Vector extends DoubleVector { return super.testTemplate(Double128Mask.class, op); // specialize } + @Override + @ForceInline + public final Double128Mask test(Test op, VectorMask m) { + return super.testTemplate(Double128Mask.class, op, (Double128Mask) m); // specialize + } + // Specialized comparisons @Override diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Double256Vector.java b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Double256Vector.java index 147d6b866d63a1bd827bc3fd035695e6c88bdc83..e265dc86288437af12ede90e5eff7bd815c4ad16 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Double256Vector.java +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Double256Vector.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 @@ -357,6 +357,12 @@ final class Double256Vector extends DoubleVector { return super.testTemplate(Double256Mask.class, op); // specialize } + @Override + @ForceInline + public final Double256Mask test(Test op, VectorMask m) { + return super.testTemplate(Double256Mask.class, op, (Double256Mask) m); // specialize + } + // Specialized comparisons @Override diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Double512Vector.java b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Double512Vector.java index e091ca9b63fd4407e36323ec029c59dc3821dad6..77b52f511d629d21b1886720d273ea802e718684 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Double512Vector.java +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Double512Vector.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 @@ -357,6 +357,12 @@ final class Double512Vector extends DoubleVector { return super.testTemplate(Double512Mask.class, op); // specialize } + @Override + @ForceInline + public final Double512Mask test(Test op, VectorMask m) { + return super.testTemplate(Double512Mask.class, op, (Double512Mask) m); // specialize + } + // Specialized comparisons @Override diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Double64Vector.java b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Double64Vector.java index a90ff9c761ca89a4ccedb06c239050046dc6c7a4..dba680a6a3cf5dce43d3ab1c9ac03063889224b1 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Double64Vector.java +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Double64Vector.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 @@ -357,6 +357,12 @@ final class Double64Vector extends DoubleVector { return super.testTemplate(Double64Mask.class, op); // specialize } + @Override + @ForceInline + public final Double64Mask test(Test op, VectorMask m) { + return super.testTemplate(Double64Mask.class, op, (Double64Mask) m); // specialize + } + // Specialized comparisons @Override diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/DoubleMaxVector.java b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/DoubleMaxVector.java index bf4ce4e6422a8a4e5fadfba200a0be293e0e341b..8c454d3f872b911d050290dd7ddc5864ce6f8c2c 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/DoubleMaxVector.java +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/DoubleMaxVector.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 @@ -357,6 +357,12 @@ final class DoubleMaxVector extends DoubleVector { return super.testTemplate(DoubleMaxMask.class, op); // specialize } + @Override + @ForceInline + public final DoubleMaxMask test(Test op, VectorMask m) { + return super.testTemplate(DoubleMaxMask.class, op, (DoubleMaxMask) m); // specialize + } + // Specialized comparisons @Override diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/DoubleVector.java b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/DoubleVector.java index 063a4bbb191e356a47a4ad7f42a772e9b3459272..4d62284bb6e1e9da8c2c6689a08a7c8e04efdd14 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/DoubleVector.java +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/DoubleVector.java @@ -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 @@ -1715,7 +1715,7 @@ public abstract class DoubleVector extends AbstractVector { else { throw new AssertionError(op); } - return maskType.cast(m.cast(this.vspecies())); + return maskType.cast(m.cast(vsp)); } int opc = opCode(op); throw new AssertionError(op); @@ -1725,11 +1725,48 @@ public abstract class DoubleVector extends AbstractVector { * {@inheritDoc} */ @Override - @ForceInline - public final + public abstract VectorMask test(VectorOperators.Test op, - VectorMask m) { - return test(op).and(m); + VectorMask m); + + /*package-private*/ + @ForceInline + final + > + M testTemplate(Class maskType, Test op, M mask) { + DoubleSpecies vsp = vspecies(); + mask.check(maskType, this); + if (opKind(op, VO_SPECIAL)) { + LongVector bits = this.viewAsIntegralLanes(); + VectorMask m = mask.cast(LongVector.species(shape())); + if (op == IS_DEFAULT) { + m = bits.compare(EQ, (long) 0, m); + } else if (op == IS_NEGATIVE) { + m = bits.compare(LT, (long) 0, m); + } + else if (op == IS_FINITE || + op == IS_NAN || + op == IS_INFINITE) { + // first kill the sign: + bits = bits.and(Long.MAX_VALUE); + // next find the bit pattern for infinity: + long infbits = (long) toBits(Double.POSITIVE_INFINITY); + // now compare: + if (op == IS_FINITE) { + m = bits.compare(LT, infbits, m); + } else if (op == IS_NAN) { + m = bits.compare(GT, infbits, m); + } else { + m = bits.compare(EQ, infbits, m); + } + } + else { + throw new AssertionError(op); + } + return maskType.cast(m.cast(vsp)); + } + int opc = opCode(op); + throw new AssertionError(op); } /** @@ -3926,12 +3963,12 @@ public abstract class DoubleVector extends AbstractVector { */ static DoubleSpecies species(VectorShape s) { Objects.requireNonNull(s); - switch (s) { - case S_64_BIT: return (DoubleSpecies) SPECIES_64; - case S_128_BIT: return (DoubleSpecies) SPECIES_128; - case S_256_BIT: return (DoubleSpecies) SPECIES_256; - case S_512_BIT: return (DoubleSpecies) SPECIES_512; - case S_Max_BIT: return (DoubleSpecies) SPECIES_MAX; + switch (s.switchKey) { + case VectorShape.SK_64_BIT: return (DoubleSpecies) SPECIES_64; + case VectorShape.SK_128_BIT: return (DoubleSpecies) SPECIES_128; + case VectorShape.SK_256_BIT: return (DoubleSpecies) SPECIES_256; + case VectorShape.SK_512_BIT: return (DoubleSpecies) SPECIES_512; + case VectorShape.SK_Max_BIT: return (DoubleSpecies) SPECIES_MAX; default: throw new IllegalArgumentException("Bad shape: " + s); } } diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Float128Vector.java b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Float128Vector.java index 88f6d76d0cb76d0d8649c1913e1981299aff18a5..1d6195486ae0e7274b66ff17a36b774c56b51358 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Float128Vector.java +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Float128Vector.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 @@ -357,6 +357,12 @@ final class Float128Vector extends FloatVector { return super.testTemplate(Float128Mask.class, op); // specialize } + @Override + @ForceInline + public final Float128Mask test(Test op, VectorMask m) { + return super.testTemplate(Float128Mask.class, op, (Float128Mask) m); // specialize + } + // Specialized comparisons @Override diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Float256Vector.java b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Float256Vector.java index 4b039df7984ce16b136c1aa9d4d34eca9a3132d9..6a2a1003cf467d0b8871e3f90c8bfdf35fde7cb8 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Float256Vector.java +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Float256Vector.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 @@ -357,6 +357,12 @@ final class Float256Vector extends FloatVector { return super.testTemplate(Float256Mask.class, op); // specialize } + @Override + @ForceInline + public final Float256Mask test(Test op, VectorMask m) { + return super.testTemplate(Float256Mask.class, op, (Float256Mask) m); // specialize + } + // Specialized comparisons @Override diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Float512Vector.java b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Float512Vector.java index 7864af72205406da5201a035e34b0c4ad5e5914a..5b29c2cca10650b26c6a5c4091f30aa8d561c2c5 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Float512Vector.java +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Float512Vector.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 @@ -357,6 +357,12 @@ final class Float512Vector extends FloatVector { return super.testTemplate(Float512Mask.class, op); // specialize } + @Override + @ForceInline + public final Float512Mask test(Test op, VectorMask m) { + return super.testTemplate(Float512Mask.class, op, (Float512Mask) m); // specialize + } + // Specialized comparisons @Override diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Float64Vector.java b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Float64Vector.java index bbdbcee1c5fb38e85568c1ed3358040b7600a810..0eea80c244fbf0fe701b1e274363395482f0a6c1 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Float64Vector.java +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Float64Vector.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 @@ -357,6 +357,12 @@ final class Float64Vector extends FloatVector { return super.testTemplate(Float64Mask.class, op); // specialize } + @Override + @ForceInline + public final Float64Mask test(Test op, VectorMask m) { + return super.testTemplate(Float64Mask.class, op, (Float64Mask) m); // specialize + } + // Specialized comparisons @Override diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/FloatMaxVector.java b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/FloatMaxVector.java index bba093b3b762e3d99ef6e621a1281b988eda9b9c..0db9aab9c57d7155119a92fbc65f6b82e810a38d 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/FloatMaxVector.java +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/FloatMaxVector.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 @@ -357,6 +357,12 @@ final class FloatMaxVector extends FloatVector { return super.testTemplate(FloatMaxMask.class, op); // specialize } + @Override + @ForceInline + public final FloatMaxMask test(Test op, VectorMask m) { + return super.testTemplate(FloatMaxMask.class, op, (FloatMaxMask) m); // specialize + } + // Specialized comparisons @Override diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/FloatVector.java b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/FloatVector.java index f78d98145149980ba767715661a2646031f4a06c..60da7eb57fcbb405136423e0888b779bdef8bda8 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/FloatVector.java +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/FloatVector.java @@ -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 @@ -1727,7 +1727,7 @@ public abstract class FloatVector extends AbstractVector { else { throw new AssertionError(op); } - return maskType.cast(m.cast(this.vspecies())); + return maskType.cast(m.cast(vsp)); } int opc = opCode(op); throw new AssertionError(op); @@ -1737,11 +1737,48 @@ public abstract class FloatVector extends AbstractVector { * {@inheritDoc} */ @Override - @ForceInline - public final + public abstract VectorMask test(VectorOperators.Test op, - VectorMask m) { - return test(op).and(m); + VectorMask m); + + /*package-private*/ + @ForceInline + final + > + M testTemplate(Class maskType, Test op, M mask) { + FloatSpecies vsp = vspecies(); + mask.check(maskType, this); + if (opKind(op, VO_SPECIAL)) { + IntVector bits = this.viewAsIntegralLanes(); + VectorMask m = mask.cast(IntVector.species(shape())); + if (op == IS_DEFAULT) { + m = bits.compare(EQ, (int) 0, m); + } else if (op == IS_NEGATIVE) { + m = bits.compare(LT, (int) 0, m); + } + else if (op == IS_FINITE || + op == IS_NAN || + op == IS_INFINITE) { + // first kill the sign: + bits = bits.and(Integer.MAX_VALUE); + // next find the bit pattern for infinity: + int infbits = (int) toBits(Float.POSITIVE_INFINITY); + // now compare: + if (op == IS_FINITE) { + m = bits.compare(LT, infbits, m); + } else if (op == IS_NAN) { + m = bits.compare(GT, infbits, m); + } else { + m = bits.compare(EQ, infbits, m); + } + } + else { + throw new AssertionError(op); + } + return maskType.cast(m.cast(vsp)); + } + int opc = opCode(op); + throw new AssertionError(op); } /** @@ -3876,12 +3913,12 @@ public abstract class FloatVector extends AbstractVector { */ static FloatSpecies species(VectorShape s) { Objects.requireNonNull(s); - switch (s) { - case S_64_BIT: return (FloatSpecies) SPECIES_64; - case S_128_BIT: return (FloatSpecies) SPECIES_128; - case S_256_BIT: return (FloatSpecies) SPECIES_256; - case S_512_BIT: return (FloatSpecies) SPECIES_512; - case S_Max_BIT: return (FloatSpecies) SPECIES_MAX; + switch (s.switchKey) { + case VectorShape.SK_64_BIT: return (FloatSpecies) SPECIES_64; + case VectorShape.SK_128_BIT: return (FloatSpecies) SPECIES_128; + case VectorShape.SK_256_BIT: return (FloatSpecies) SPECIES_256; + case VectorShape.SK_512_BIT: return (FloatSpecies) SPECIES_512; + case VectorShape.SK_Max_BIT: return (FloatSpecies) SPECIES_MAX; default: throw new IllegalArgumentException("Bad shape: " + s); } } diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Int128Vector.java b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Int128Vector.java index 3a88ba76e8044a25ea1642b52d61fe375c4039a6..3baf712aa7c5a55ea955e3d7be349ef34184dabc 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Int128Vector.java +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Int128Vector.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 @@ -370,6 +370,12 @@ final class Int128Vector extends IntVector { return super.testTemplate(Int128Mask.class, op); // specialize } + @Override + @ForceInline + public final Int128Mask test(Test op, VectorMask m) { + return super.testTemplate(Int128Mask.class, op, (Int128Mask) m); // specialize + } + // Specialized comparisons @Override diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Int256Vector.java b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Int256Vector.java index ffc560e5f52ec6b0512886e12919fe141f719c3e..a82f1cf1d072779e2f54c3b9e6066e56197f1916 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Int256Vector.java +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Int256Vector.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 @@ -370,6 +370,12 @@ final class Int256Vector extends IntVector { return super.testTemplate(Int256Mask.class, op); // specialize } + @Override + @ForceInline + public final Int256Mask test(Test op, VectorMask m) { + return super.testTemplate(Int256Mask.class, op, (Int256Mask) m); // specialize + } + // Specialized comparisons @Override diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Int512Vector.java b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Int512Vector.java index a2ff6d515e372a9bfa5164a9999b7b69f7bf6cf8..40b7246b63ffac9159234bb48bd246d1441c3100 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Int512Vector.java +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Int512Vector.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 @@ -370,6 +370,12 @@ final class Int512Vector extends IntVector { return super.testTemplate(Int512Mask.class, op); // specialize } + @Override + @ForceInline + public final Int512Mask test(Test op, VectorMask m) { + return super.testTemplate(Int512Mask.class, op, (Int512Mask) m); // specialize + } + // Specialized comparisons @Override diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Int64Vector.java b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Int64Vector.java index 996f35ac15d480b07570c9ac01f6ccb9cc7feb76..59c54a6007bb1527f8a46796023fb115b7551f25 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Int64Vector.java +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Int64Vector.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 @@ -370,6 +370,12 @@ final class Int64Vector extends IntVector { return super.testTemplate(Int64Mask.class, op); // specialize } + @Override + @ForceInline + public final Int64Mask test(Test op, VectorMask m) { + return super.testTemplate(Int64Mask.class, op, (Int64Mask) m); // specialize + } + // Specialized comparisons @Override diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/IntMaxVector.java b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/IntMaxVector.java index cfc645fcd6b76a53402fc682b9b85c8bc446ccd4..58588448c06e03ef5c2c9b98538e2ff69e819bb7 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/IntMaxVector.java +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/IntMaxVector.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 @@ -370,6 +370,12 @@ final class IntMaxVector extends IntVector { return super.testTemplate(IntMaxMask.class, op); // specialize } + @Override + @ForceInline + public final IntMaxMask test(Test op, VectorMask m) { + return super.testTemplate(IntMaxMask.class, op, (IntMaxMask) m); // specialize + } + // Specialized comparisons @Override diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/IntVector.java b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/IntVector.java index c80b61cb7a2eed95a2126b9188f14e27bfcbc915..e5033ac5366a4af671a38665784406a8de34530e 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/IntVector.java +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/IntVector.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 @@ -1854,12 +1854,11 @@ public abstract class IntVector extends AbstractVector { M testTemplate(Class maskType, Test op) { IntSpecies vsp = vspecies(); if (opKind(op, VO_SPECIAL)) { - IntVector bits = this.viewAsIntegralLanes(); VectorMask m; if (op == IS_DEFAULT) { - m = bits.compare(EQ, (int) 0); + m = compare(EQ, (int) 0); } else if (op == IS_NEGATIVE) { - m = bits.compare(LT, (int) 0); + m = compare(LT, (int) 0); } else { throw new AssertionError(op); @@ -1874,11 +1873,31 @@ public abstract class IntVector extends AbstractVector { * {@inheritDoc} */ @Override - @ForceInline - public final + public abstract VectorMask test(VectorOperators.Test op, - VectorMask m) { - return test(op).and(m); + VectorMask m); + + /*package-private*/ + @ForceInline + final + > + M testTemplate(Class maskType, Test op, M mask) { + IntSpecies vsp = vspecies(); + mask.check(maskType, this); + if (opKind(op, VO_SPECIAL)) { + VectorMask m = mask; + if (op == IS_DEFAULT) { + m = compare(EQ, (int) 0, m); + } else if (op == IS_NEGATIVE) { + m = compare(LT, (int) 0, m); + } + else { + throw new AssertionError(op); + } + return maskType.cast(m); + } + int opc = opCode(op); + throw new AssertionError(op); } /** @@ -4042,12 +4061,12 @@ public abstract class IntVector extends AbstractVector { */ static IntSpecies species(VectorShape s) { Objects.requireNonNull(s); - switch (s) { - case S_64_BIT: return (IntSpecies) SPECIES_64; - case S_128_BIT: return (IntSpecies) SPECIES_128; - case S_256_BIT: return (IntSpecies) SPECIES_256; - case S_512_BIT: return (IntSpecies) SPECIES_512; - case S_Max_BIT: return (IntSpecies) SPECIES_MAX; + switch (s.switchKey) { + case VectorShape.SK_64_BIT: return (IntSpecies) SPECIES_64; + case VectorShape.SK_128_BIT: return (IntSpecies) SPECIES_128; + case VectorShape.SK_256_BIT: return (IntSpecies) SPECIES_256; + case VectorShape.SK_512_BIT: return (IntSpecies) SPECIES_512; + case VectorShape.SK_Max_BIT: return (IntSpecies) SPECIES_MAX; default: throw new IllegalArgumentException("Bad shape: " + s); } } diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Long128Vector.java b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Long128Vector.java index aad676d8fcebd4623e6ae8074c802a9157707d1a..7a11c0005a4f47fb6497dd3cc4a52792a7ad3195 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Long128Vector.java +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Long128Vector.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 @@ -365,6 +365,12 @@ final class Long128Vector extends LongVector { return super.testTemplate(Long128Mask.class, op); // specialize } + @Override + @ForceInline + public final Long128Mask test(Test op, VectorMask m) { + return super.testTemplate(Long128Mask.class, op, (Long128Mask) m); // specialize + } + // Specialized comparisons @Override diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Long256Vector.java b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Long256Vector.java index 85f1e54f24290f5bdb38e1998ed9064b4526181d..ad4057dc07083bc2fca7390c6a9c407bd4ac82f9 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Long256Vector.java +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Long256Vector.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 @@ -365,6 +365,12 @@ final class Long256Vector extends LongVector { return super.testTemplate(Long256Mask.class, op); // specialize } + @Override + @ForceInline + public final Long256Mask test(Test op, VectorMask m) { + return super.testTemplate(Long256Mask.class, op, (Long256Mask) m); // specialize + } + // Specialized comparisons @Override diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Long512Vector.java b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Long512Vector.java index 1642b885f348a096bb9a3263d398abcceff97996..6f7bee397a15c8cedcee8fcd09e073d3d7486f63 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Long512Vector.java +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Long512Vector.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 @@ -365,6 +365,12 @@ final class Long512Vector extends LongVector { return super.testTemplate(Long512Mask.class, op); // specialize } + @Override + @ForceInline + public final Long512Mask test(Test op, VectorMask m) { + return super.testTemplate(Long512Mask.class, op, (Long512Mask) m); // specialize + } + // Specialized comparisons @Override diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Long64Vector.java b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Long64Vector.java index 3e67506c392157e666590640838cd45774343b66..e7ab1241f4e575016df0c938263ccfad2fb01b1f 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Long64Vector.java +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Long64Vector.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 @@ -365,6 +365,12 @@ final class Long64Vector extends LongVector { return super.testTemplate(Long64Mask.class, op); // specialize } + @Override + @ForceInline + public final Long64Mask test(Test op, VectorMask m) { + return super.testTemplate(Long64Mask.class, op, (Long64Mask) m); // specialize + } + // Specialized comparisons @Override diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/LongMaxVector.java b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/LongMaxVector.java index 2078dbec65b432adfb6dcb138dcf682180dcb0e9..56ce68f1fc327e48baec96480a4f33c911a61bf3 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/LongMaxVector.java +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/LongMaxVector.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 @@ -365,6 +365,12 @@ final class LongMaxVector extends LongVector { return super.testTemplate(LongMaxMask.class, op); // specialize } + @Override + @ForceInline + public final LongMaxMask test(Test op, VectorMask m) { + return super.testTemplate(LongMaxMask.class, op, (LongMaxMask) m); // specialize + } + // Specialized comparisons @Override diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/LongVector.java b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/LongVector.java index 6934469b2133191473349f3719ebc6efb0c44b9f..37ba71896791229a1a3189ae2cdb902f649b20d4 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/LongVector.java +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/LongVector.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 @@ -1767,12 +1767,11 @@ public abstract class LongVector extends AbstractVector { M testTemplate(Class maskType, Test op) { LongSpecies vsp = vspecies(); if (opKind(op, VO_SPECIAL)) { - LongVector bits = this.viewAsIntegralLanes(); VectorMask m; if (op == IS_DEFAULT) { - m = bits.compare(EQ, (long) 0); + m = compare(EQ, (long) 0); } else if (op == IS_NEGATIVE) { - m = bits.compare(LT, (long) 0); + m = compare(LT, (long) 0); } else { throw new AssertionError(op); @@ -1787,11 +1786,31 @@ public abstract class LongVector extends AbstractVector { * {@inheritDoc} */ @Override - @ForceInline - public final + public abstract VectorMask test(VectorOperators.Test op, - VectorMask m) { - return test(op).and(m); + VectorMask m); + + /*package-private*/ + @ForceInline + final + > + M testTemplate(Class maskType, Test op, M mask) { + LongSpecies vsp = vspecies(); + mask.check(maskType, this); + if (opKind(op, VO_SPECIAL)) { + VectorMask m = mask; + if (op == IS_DEFAULT) { + m = compare(EQ, (long) 0, m); + } else if (op == IS_NEGATIVE) { + m = compare(LT, (long) 0, m); + } + else { + throw new AssertionError(op); + } + return maskType.cast(m); + } + int opc = opCode(op); + throw new AssertionError(op); } /** @@ -3968,12 +3987,12 @@ public abstract class LongVector extends AbstractVector { */ static LongSpecies species(VectorShape s) { Objects.requireNonNull(s); - switch (s) { - case S_64_BIT: return (LongSpecies) SPECIES_64; - case S_128_BIT: return (LongSpecies) SPECIES_128; - case S_256_BIT: return (LongSpecies) SPECIES_256; - case S_512_BIT: return (LongSpecies) SPECIES_512; - case S_Max_BIT: return (LongSpecies) SPECIES_MAX; + switch (s.switchKey) { + case VectorShape.SK_64_BIT: return (LongSpecies) SPECIES_64; + case VectorShape.SK_128_BIT: return (LongSpecies) SPECIES_128; + case VectorShape.SK_256_BIT: return (LongSpecies) SPECIES_256; + case VectorShape.SK_512_BIT: return (LongSpecies) SPECIES_512; + case VectorShape.SK_Max_BIT: return (LongSpecies) SPECIES_MAX; default: throw new IllegalArgumentException("Bad shape: " + s); } } diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Short128Vector.java b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Short128Vector.java index 93bf40153a7e4cfc7110ba2fddc90c168b118956..ce7e3ca8c1826255a878a16a2e6e8c47882420be 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Short128Vector.java +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Short128Vector.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 @@ -370,6 +370,12 @@ final class Short128Vector extends ShortVector { return super.testTemplate(Short128Mask.class, op); // specialize } + @Override + @ForceInline + public final Short128Mask test(Test op, VectorMask m) { + return super.testTemplate(Short128Mask.class, op, (Short128Mask) m); // specialize + } + // Specialized comparisons @Override diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Short256Vector.java b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Short256Vector.java index 805f89bcdd932b1f52efe54ee879938e8f748483..3d7b00ddcd0f00b0ff98d0602a77ee747cb6203b 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Short256Vector.java +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Short256Vector.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 @@ -370,6 +370,12 @@ final class Short256Vector extends ShortVector { return super.testTemplate(Short256Mask.class, op); // specialize } + @Override + @ForceInline + public final Short256Mask test(Test op, VectorMask m) { + return super.testTemplate(Short256Mask.class, op, (Short256Mask) m); // specialize + } + // Specialized comparisons @Override diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Short512Vector.java b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Short512Vector.java index 51d728529380e2b27013b09f889a64f776b7948e..2d23dcae93fadecf6b9dde444b634c0398452cc5 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Short512Vector.java +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Short512Vector.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 @@ -370,6 +370,12 @@ final class Short512Vector extends ShortVector { return super.testTemplate(Short512Mask.class, op); // specialize } + @Override + @ForceInline + public final Short512Mask test(Test op, VectorMask m) { + return super.testTemplate(Short512Mask.class, op, (Short512Mask) m); // specialize + } + // Specialized comparisons @Override diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Short64Vector.java b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Short64Vector.java index 97ac8fe07cb91f51042cbcb317a4c5a4dcd86d1e..f7e0c0162d311ae21b02b87e2680800b638215de 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Short64Vector.java +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Short64Vector.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 @@ -370,6 +370,12 @@ final class Short64Vector extends ShortVector { return super.testTemplate(Short64Mask.class, op); // specialize } + @Override + @ForceInline + public final Short64Mask test(Test op, VectorMask m) { + return super.testTemplate(Short64Mask.class, op, (Short64Mask) m); // specialize + } + // Specialized comparisons @Override diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/ShortMaxVector.java b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/ShortMaxVector.java index c0ec9ee8b4ecccc5110ef2aa9710f20c9326e1a2..154096d9d6f6c2d1664cc5617db41840481fbf3b 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/ShortMaxVector.java +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/ShortMaxVector.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 @@ -370,6 +370,12 @@ final class ShortMaxVector extends ShortVector { return super.testTemplate(ShortMaxMask.class, op); // specialize } + @Override + @ForceInline + public final ShortMaxMask test(Test op, VectorMask m) { + return super.testTemplate(ShortMaxMask.class, op, (ShortMaxMask) m); // specialize + } + // Specialized comparisons @Override diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/ShortVector.java b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/ShortVector.java index b3c89e87cc48d2d19018f6f92a4f1c257dcea72d..8c6dd4718f75a5d022d9d01c83f1a62bfd37b0f0 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/ShortVector.java +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/ShortVector.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 @@ -1855,12 +1855,11 @@ public abstract class ShortVector extends AbstractVector { M testTemplate(Class maskType, Test op) { ShortSpecies vsp = vspecies(); if (opKind(op, VO_SPECIAL)) { - ShortVector bits = this.viewAsIntegralLanes(); VectorMask m; if (op == IS_DEFAULT) { - m = bits.compare(EQ, (short) 0); + m = compare(EQ, (short) 0); } else if (op == IS_NEGATIVE) { - m = bits.compare(LT, (short) 0); + m = compare(LT, (short) 0); } else { throw new AssertionError(op); @@ -1875,11 +1874,31 @@ public abstract class ShortVector extends AbstractVector { * {@inheritDoc} */ @Override - @ForceInline - public final + public abstract VectorMask test(VectorOperators.Test op, - VectorMask m) { - return test(op).and(m); + VectorMask m); + + /*package-private*/ + @ForceInline + final + > + M testTemplate(Class maskType, Test op, M mask) { + ShortSpecies vsp = vspecies(); + mask.check(maskType, this); + if (opKind(op, VO_SPECIAL)) { + VectorMask m = mask; + if (op == IS_DEFAULT) { + m = compare(EQ, (short) 0, m); + } else if (op == IS_NEGATIVE) { + m = compare(LT, (short) 0, m); + } + else { + throw new AssertionError(op); + } + return maskType.cast(m); + } + int opc = opCode(op); + throw new AssertionError(op); } /** @@ -4311,12 +4330,12 @@ public abstract class ShortVector extends AbstractVector { */ static ShortSpecies species(VectorShape s) { Objects.requireNonNull(s); - switch (s) { - case S_64_BIT: return (ShortSpecies) SPECIES_64; - case S_128_BIT: return (ShortSpecies) SPECIES_128; - case S_256_BIT: return (ShortSpecies) SPECIES_256; - case S_512_BIT: return (ShortSpecies) SPECIES_512; - case S_Max_BIT: return (ShortSpecies) SPECIES_MAX; + switch (s.switchKey) { + case VectorShape.SK_64_BIT: return (ShortSpecies) SPECIES_64; + case VectorShape.SK_128_BIT: return (ShortSpecies) SPECIES_128; + case VectorShape.SK_256_BIT: return (ShortSpecies) SPECIES_256; + case VectorShape.SK_512_BIT: return (ShortSpecies) SPECIES_512; + case VectorShape.SK_Max_BIT: return (ShortSpecies) SPECIES_MAX; default: throw new IllegalArgumentException("Bad shape: " + s); } } diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/X-Vector.java.template b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/X-Vector.java.template index 1cd50a11b8b13877fb2935b889bd0a3275a2792e..6c5ed6b9c13fd6b66c7001c10544e235a89dee43 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/X-Vector.java.template +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/X-Vector.java.template @@ -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 @@ -2128,12 +2128,14 @@ public abstract class $abstractvectortype$ extends AbstractVector<$Boxtype$> { M testTemplate(Class maskType, Test op) { $Type$Species vsp = vspecies(); if (opKind(op, VO_SPECIAL)) { +#if[FP] $Bitstype$Vector bits = this.viewAsIntegralLanes(); +#end[FP] VectorMask<$Boxbitstype$> m; if (op == IS_DEFAULT) { - m = bits.compare(EQ, ($bitstype$) 0); + m = {#if[FP]?bits.}compare(EQ, ($bitstype$) 0); } else if (op == IS_NEGATIVE) { - m = bits.compare(LT, ($bitstype$) 0); + m = {#if[FP]?bits.}compare(LT, ($bitstype$) 0); } #if[FP] else if (op == IS_FINITE || @@ -2156,7 +2158,7 @@ public abstract class $abstractvectortype$ extends AbstractVector<$Boxtype$> { else { throw new AssertionError(op); } - return maskType.cast(m{#if[FP]?.cast(this.vspecies())}); + return maskType.cast(m{#if[FP]?.cast(vsp)}); } int opc = opCode(op); throw new AssertionError(op); @@ -2166,11 +2168,54 @@ public abstract class $abstractvectortype$ extends AbstractVector<$Boxtype$> { * {@inheritDoc} */ @Override - @ForceInline - public final + public abstract VectorMask<$Boxtype$> test(VectorOperators.Test op, - VectorMask<$Boxtype$> m) { - return test(op).and(m); + VectorMask<$Boxtype$> m); + + /*package-private*/ + @ForceInline + final + > + M testTemplate(Class maskType, Test op, M mask) { + $Type$Species vsp = vspecies(); + mask.check(maskType, this); + if (opKind(op, VO_SPECIAL)) { +#if[FP] + $Bitstype$Vector bits = this.viewAsIntegralLanes(); + VectorMask<$Boxbitstype$> m = mask.cast($Bitstype$Vector.species(shape())); +#else[FP] + VectorMask<$Boxbitstype$> m = mask; +#end[FP] + if (op == IS_DEFAULT) { + m = {#if[FP]?bits.}compare(EQ, ($bitstype$) 0, m); + } else if (op == IS_NEGATIVE) { + m = {#if[FP]?bits.}compare(LT, ($bitstype$) 0, m); + } +#if[FP] + else if (op == IS_FINITE || + op == IS_NAN || + op == IS_INFINITE) { + // first kill the sign: + bits = bits.and($Boxbitstype$.MAX_VALUE); + // next find the bit pattern for infinity: + $bitstype$ infbits = ($bitstype$) toBits($Boxtype$.POSITIVE_INFINITY); + // now compare: + if (op == IS_FINITE) { + m = bits.compare(LT, infbits, m); + } else if (op == IS_NAN) { + m = bits.compare(GT, infbits, m); + } else { + m = bits.compare(EQ, infbits, m); + } + } +#end[FP] + else { + throw new AssertionError(op); + } + return maskType.cast(m{#if[FP]?.cast(vsp)}); + } + int opc = opCode(op); + throw new AssertionError(op); } /** @@ -5498,12 +5543,12 @@ public abstract class $abstractvectortype$ extends AbstractVector<$Boxtype$> { */ static $Type$Species species(VectorShape s) { Objects.requireNonNull(s); - switch (s) { - case S_64_BIT: return ($Type$Species) SPECIES_64; - case S_128_BIT: return ($Type$Species) SPECIES_128; - case S_256_BIT: return ($Type$Species) SPECIES_256; - case S_512_BIT: return ($Type$Species) SPECIES_512; - case S_Max_BIT: return ($Type$Species) SPECIES_MAX; + switch (s.switchKey) { + case VectorShape.SK_64_BIT: return ($Type$Species) SPECIES_64; + case VectorShape.SK_128_BIT: return ($Type$Species) SPECIES_128; + case VectorShape.SK_256_BIT: return ($Type$Species) SPECIES_256; + case VectorShape.SK_512_BIT: return ($Type$Species) SPECIES_512; + case VectorShape.SK_Max_BIT: return ($Type$Species) SPECIES_MAX; default: throw new IllegalArgumentException("Bad shape: " + s); } } diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/X-VectorBits.java.template b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/X-VectorBits.java.template index 2f1004f645039436642988e28d3b09b4da02044a..ec6e714f218507cf78533016960837d34ec7d52c 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/X-VectorBits.java.template +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/X-VectorBits.java.template @@ -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 @@ -374,6 +374,12 @@ final class $vectortype$ extends $abstractvectortype$ { return super.testTemplate($masktype$.class, op); // specialize } + @Override + @ForceInline + public final $masktype$ test(Test op, VectorMask<$Boxtype$> m) { + return super.testTemplate($masktype$.class, op, ($masktype$) m); // specialize + } + // Specialized comparisons @Override diff --git a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.aarch64/src/jdk/vm/ci/aarch64/AArch64.java b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.aarch64/src/jdk/vm/ci/aarch64/AArch64.java index c2a7fa2b5cd9f124b4dd22811ae1e30751dc9a87..a4b5ba3ffa5da4579537f9185a1d3c55c979455e 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.aarch64/src/jdk/vm/ci/aarch64/AArch64.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.aarch64/src/jdk/vm/ci/aarch64/AArch64.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 @@ -177,6 +177,7 @@ public class AArch64 extends Architecture { SHA3, SHA512, SVE, + PACA, SVE2, STXR_PREFETCH, A53MAC, diff --git a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/MetaUtil.java b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/MetaUtil.java index 528bb34e0592cefa93ab35cc1591c017134d4413..54a55dc31222b0738aeb71a7cfe041a825857f94 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/MetaUtil.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/MetaUtil.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 @@ -27,6 +27,11 @@ package jdk.vm.ci.meta; */ public class MetaUtil { + public static final char PACKAGE_SEPARATOR_INTERNAL = '/'; + public static final char HIDDEN_SEPARATOR_INTERNAL = '.'; + public static final char PACKAGE_SEPARATOR_JAVA = HIDDEN_SEPARATOR_INTERNAL; + public static final char HIDDEN_SEPARATOR_JAVA = PACKAGE_SEPARATOR_INTERNAL; + /** * Extends the functionality of {@link Class#getSimpleName()} to include a non-empty string for * anonymous and local classes. @@ -87,25 +92,27 @@ public class MetaUtil { } /** - * Classes for lambdas can have {@code /} characters that are not package separators. These are - * distinguished by being followed by a character that is not a + * Hidden classes have {@code /} characters in their internal names and {@code .} characters in their names returned + * by {@link Class#getName()} that are not package separators. + * These are distinguished by being followed by a character that is not a * {@link Character#isJavaIdentifierStart(char)} (e.g., * "jdk.vm.ci.runtime.test.TypeUniverse$$Lambda$1/869601985"). + * + * @param name the name to perform the replacements on + * @param packageSeparator the {@link Character} used as the package separator, e.g. {@code /} in internal form + * @param hiddenSeparator the {@link Character} used as the hidden class separator, e.g. {@code .} in internal form */ - private static String replacePackageSeparatorsWithDot(String name) { + private static String replacePackageAndHiddenSeparators(String name, Character packageSeparator, Character hiddenSeparator) { + int index = name.indexOf(hiddenSeparator); // check if it's a hidden class int length = name.length(); - int i = 0; StringBuilder buf = new StringBuilder(length); - while (i < length - 1) { - char ch = name.charAt(i); - if (ch == '/' && Character.isJavaIdentifierStart(name.charAt(i + 1))) { - buf.append('.'); - } else { - buf.append(ch); - } - i++; + if (index < 0) { + buf.append(name.replace(packageSeparator, hiddenSeparator)); + } else { + buf.append(name.substring(0, index).replace(packageSeparator, hiddenSeparator)); + buf.append(packageSeparator); + buf.append(name.substring(index + 1)); } - buf.append(name.charAt(length - 1)); return buf.toString(); } @@ -122,9 +129,10 @@ public class MetaUtil { public static String internalNameToJava(String name, boolean qualified, boolean classForNameCompatible) { switch (name.charAt(0)) { case 'L': { - String result = replacePackageSeparatorsWithDot(name.substring(1, name.length() - 1)); + String type = name.substring(1, name.length() - 1); + String result = replacePackageAndHiddenSeparators(type, PACKAGE_SEPARATOR_INTERNAL, HIDDEN_SEPARATOR_INTERNAL); if (!qualified) { - final int lastDot = result.lastIndexOf('.'); + final int lastDot = result.lastIndexOf(HIDDEN_SEPARATOR_INTERNAL); if (lastDot != -1) { result = result.substring(lastDot + 1); } @@ -132,7 +140,11 @@ public class MetaUtil { return result; } case '[': - return classForNameCompatible ? replacePackageSeparatorsWithDot(name) : internalNameToJava(name.substring(1), qualified, classForNameCompatible) + "[]"; + if (classForNameCompatible) { + return replacePackageAndHiddenSeparators(name, PACKAGE_SEPARATOR_INTERNAL, HIDDEN_SEPARATOR_INTERNAL); + } else { + return internalNameToJava(name.substring(1), qualified, false) + "[]"; + } default: if (name.length() != 1) { throw new IllegalArgumentException("Illegal internal name: " + name); @@ -213,7 +225,7 @@ public class MetaUtil { public static String toInternalName(String className) { if (className.startsWith("[")) { /* Already in the correct array style. */ - return className.replace('.', '/'); + return replacePackageAndHiddenSeparators(className, PACKAGE_SEPARATOR_JAVA, HIDDEN_SEPARATOR_JAVA); } StringBuilder result = new StringBuilder(); @@ -252,7 +264,9 @@ public class MetaUtil { result.append("V"); break; default: - result.append("L").append(base.replace('.', '/')).append(";"); + result.append("L") + .append(replacePackageAndHiddenSeparators(base, PACKAGE_SEPARATOR_JAVA, HIDDEN_SEPARATOR_JAVA)) + .append(";"); break; } return result.toString(); diff --git a/src/jdk.jartool/share/classes/sun/security/tools/jarsigner/Main.java b/src/jdk.jartool/share/classes/sun/security/tools/jarsigner/Main.java index 87ff579a7c15dbfd75e5b46d08d3fde3f34b4617..1b9e23f0fde8eace75184933e53e9449e96ca82e 100644 --- a/src/jdk.jartool/share/classes/sun/security/tools/jarsigner/Main.java +++ b/src/jdk.jartool/share/classes/sun/security/tools/jarsigner/Main.java @@ -30,6 +30,7 @@ import java.net.UnknownHostException; import java.net.URLClassLoader; import java.security.cert.CertPathValidatorException; import java.security.cert.PKIXBuilderParameters; +import java.security.interfaces.ECKey; import java.util.*; import java.util.stream.Collectors; import java.util.zip.*; @@ -1021,6 +1022,8 @@ public class Main { si.getDigestAlgorithmId(), si.getDigestEncryptionAlgorithmId(), si.getAuthenticatedAttributes() == null); + AlgorithmId encAlgId = si.getDigestEncryptionAlgorithmId(); + AlgorithmParameters sigAlgParams = encAlgId.getParameters(); PublicKey key = signer.getPublicKey(); PKCS7 tsToken = si.getTsToken(); if (tsToken != null) { @@ -1035,6 +1038,8 @@ public class Main { tsSi.getDigestAlgorithmId(), tsSi.getDigestEncryptionAlgorithmId(), tsSi.getAuthenticatedAttributes() == null); + AlgorithmId tsEncAlgId = tsSi.getDigestEncryptionAlgorithmId(); + AlgorithmParameters tsSigAlgParams = tsEncAlgId.getParameters(); Calendar c = Calendar.getInstance( TimeZone.getTimeZone("UTC"), Locale.getDefault(Locale.Category.FORMAT)); @@ -1049,13 +1054,13 @@ public class Main { history = String.format( rb.getString("history.with.ts"), signer.getSubjectX500Principal(), - verifyWithWeak(digestAlg, DIGEST_PRIMITIVE_SET, false, jcp), - verifyWithWeak(sigAlg, SIG_PRIMITIVE_SET, false, jcp), + verifyWithWeak(digestAlg, DIGEST_PRIMITIVE_SET, false, jcp, null), + verifyWithWeak(sigAlg, SIG_PRIMITIVE_SET, false, jcp, sigAlgParams), verifyWithWeak(key, jcp), c, tsSigner.getSubjectX500Principal(), - verifyWithWeak(tsDigestAlg, DIGEST_PRIMITIVE_SET, true, jcpts), - verifyWithWeak(tsSigAlg, SIG_PRIMITIVE_SET, true, jcpts), + verifyWithWeak(tsDigestAlg, DIGEST_PRIMITIVE_SET, true, jcpts, null), + verifyWithWeak(tsSigAlg, SIG_PRIMITIVE_SET, true, jcpts, tsSigAlgParams), verifyWithWeak(tsKey, jcpts)); } else { JarConstraintsParameters jcp = @@ -1063,8 +1068,8 @@ public class Main { history = String.format( rb.getString("history.without.ts"), signer.getSubjectX500Principal(), - verifyWithWeak(digestAlg, DIGEST_PRIMITIVE_SET, false, jcp), - verifyWithWeak(sigAlg, SIG_PRIMITIVE_SET, false, jcp), + verifyWithWeak(digestAlg, DIGEST_PRIMITIVE_SET, false, jcp, null), + verifyWithWeak(sigAlg, SIG_PRIMITIVE_SET, false, jcp, sigAlgParams), verifyWithWeak(key, jcp)); } } catch (Exception e) { @@ -1240,13 +1245,13 @@ public class Main { if ((legacyAlg & 8) == 8) { warnings.add(String.format( rb.getString("The.1.signing.key.has.a.keysize.of.2.which.is.considered.a.security.risk..This.key.size.will.be.disabled.in.a.future.update."), - privateKey.getAlgorithm(), KeyUtil.getKeySize(privateKey))); + KeyUtil.fullDisplayAlgName(privateKey), KeyUtil.getKeySize(privateKey))); } if ((disabledAlg & 8) == 8) { errors.add(String.format( rb.getString("The.1.signing.key.has.a.keysize.of.2.which.is.considered.a.security.risk.and.is.disabled."), - privateKey.getAlgorithm(), KeyUtil.getKeySize(privateKey))); + KeyUtil.fullDisplayAlgName(privateKey), KeyUtil.getKeySize(privateKey))); } } else { if ((legacyAlg & 1) != 0) { @@ -1270,7 +1275,7 @@ public class Main { if ((legacyAlg & 8) == 8) { warnings.add(String.format( rb.getString("The.1.signing.key.has.a.keysize.of.2.which.is.considered.a.security.risk..This.key.size.will.be.disabled.in.a.future.update."), - weakPublicKey.getAlgorithm(), KeyUtil.getKeySize(weakPublicKey))); + KeyUtil.fullDisplayAlgName(weakPublicKey), KeyUtil.getKeySize(weakPublicKey))); } } @@ -1393,7 +1398,7 @@ public class Main { } private String verifyWithWeak(String alg, Set primitiveSet, - boolean tsa, JarConstraintsParameters jcp) { + boolean tsa, JarConstraintsParameters jcp, AlgorithmParameters algParams) { try { JAR_DISABLED_CHECK.permits(alg, jcp, false); @@ -1401,9 +1406,18 @@ public class Main { disabledAlgFound = true; return String.format(rb.getString("with.disabled"), alg); } + if (algParams != null) { + try { + JAR_DISABLED_CHECK.permits(algParams, jcp); + } catch (CertPathValidatorException e) { + disabledAlgFound = true; + return String.format(rb.getString("with.algparams.disabled"), + alg, algParams); + } + } + try { LEGACY_CHECK.permits(alg, jcp, false); - return alg; } catch (CertPathValidatorException e) { if (primitiveSet == SIG_PRIMITIVE_SET) { legacyAlg |= 2; @@ -1419,6 +1433,17 @@ public class Main { } return String.format(rb.getString("with.weak"), alg); } + if (algParams != null) { + try { + LEGACY_CHECK.permits(algParams, jcp); + } catch (CertPathValidatorException e) { + legacyAlg |= 2; + legacySigAlg = alg; + return String.format(rb.getString("with.algparams.weak"), + alg, algParams); + } + } + return alg; } private String verifyWithWeak(PublicKey key, JarConstraintsParameters jcp) { @@ -1427,7 +1452,12 @@ public class Main { JAR_DISABLED_CHECK.permits(key.getAlgorithm(), jcp, true); } catch (CertPathValidatorException e) { disabledAlgFound = true; - return String.format(rb.getString("key.bit.disabled"), kLen); + if (key instanceof ECKey) { + return String.format(rb.getString("key.bit.eccurve.disabled"), kLen, + KeyUtil.fullDisplayAlgName(key)); + } else { + return String.format(rb.getString("key.bit.disabled"), kLen); + } } try { LEGACY_CHECK.permits(key.getAlgorithm(), jcp, true); @@ -1439,7 +1469,12 @@ public class Main { } catch (CertPathValidatorException e) { weakPublicKey = key; legacyAlg |= 8; - return String.format(rb.getString("key.bit.weak"), kLen); + if (key instanceof ECKey) { + return String.format(rb.getString("key.bit.eccurve.weak"), kLen, + KeyUtil.fullDisplayAlgName(key)); + } else { + return String.format(rb.getString("key.bit.weak"), kLen); + } } } @@ -1492,7 +1527,12 @@ public class Main { try { CERTPATH_DISABLED_CHECK.permits(key.getAlgorithm(), cpcp, true); } catch (CertPathValidatorException e) { - return String.format(rb.getString("key.bit.disabled"), kLen); + if (key instanceof ECKey) { + return String.format(rb.getString("key.bit.eccurve.disabled"), kLen, + KeyUtil.fullDisplayAlgName(key)); + } else { + return String.format(rb.getString("key.bit.disabled"), kLen); + } } try { LEGACY_CHECK.permits(key.getAlgorithm(), cpcp, true); @@ -1502,7 +1542,12 @@ public class Main { return rb.getString("unknown.size"); } } catch (CertPathValidatorException e) { - return String.format(rb.getString("key.bit.weak"), kLen); + if (key instanceof ECKey) { + return String.format(rb.getString("key.bit.eccurve.weak"), kLen, + KeyUtil.fullDisplayAlgName(key)); + } else { + return String.format(rb.getString("key.bit.weak"), kLen); + } } } @@ -2185,7 +2230,7 @@ public class Main { && !KeyStoreUtil.isWindowsKeyStore(storetype)) { storepass = getPass (rb.getString("Enter.Passphrase.for.keystore.")); - } else if (!token && storepass == null && prompt) { + } else if (!token && storepass == null && prompt && !protectedPath) { storepass = getPass (rb.getString("Enter.Passphrase.for.keystore.")); } diff --git a/src/jdk.jartool/share/classes/sun/security/tools/jarsigner/Resources.java b/src/jdk.jartool/share/classes/sun/security/tools/jarsigner/Resources.java index 265af66f9b363af8ee2d4af118ec8acb362b89e0..37a1f24f90d018b452ad5482ceee51e4ff389781 100644 --- a/src/jdk.jartool/share/classes/sun/security/tools/jarsigner/Resources.java +++ b/src/jdk.jartool/share/classes/sun/security/tools/jarsigner/Resources.java @@ -176,10 +176,14 @@ public class Resources extends java.util.ListResourceBundle { {"history.nobk", "- Missing block file for signature-related file META-INF/%s.SF"}, {"with.weak", "%s (weak)"}, + {"with.algparams.weak", "%1$s using %2$s (weak)"}, {"with.disabled", "%s (disabled)"}, + {"with.algparams.disabled", "%1$s using %2$s (disabled)"}, {"key.bit", "%d-bit key"}, {"key.bit.weak", "%d-bit key (weak)"}, + {"key.bit.eccurve.weak", "%1$d-bit %2$s key (weak)"}, {"key.bit.disabled", "%d-bit key (disabled)"}, + {"key.bit.eccurve.disabled", "%1$d-bit %2$s key (disabled)"}, {"unknown.size", "unknown size"}, {"extra.attributes.detected", "POSIX file permission and/or symlink attributes detected. These attributes are ignored when signing and are not protected by the signature."}, diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ClassWriterImpl.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ClassWriterImpl.java index 3b1b8537bf0a6933a8c1bdb816fded501f9ad8b6..45b10dc89e16241d7c5519a26b94d211c98487e0 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ClassWriterImpl.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ClassWriterImpl.java @@ -253,7 +253,7 @@ public class ClassWriterImpl extends SubWriterHolderWriter implements ClassWrite */ private Content getTreeForClassHelper(TypeMirror type) { Content content = new ContentBuilder(); - if (type.equals(typeElement.asType())) { + if (utils.typeUtils.isSameType(type, typeElement.asType())) { Content typeParameters = getTypeParameterLinks( new HtmlLinkInfo(configuration, HtmlLinkInfo.Kind.TREE, typeElement)); diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlDoclet.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlDoclet.java index b33c39005447de519c637160a8e0dc87d7761039..e8fb77654d16521783e76c54e4b6368ab62aa26f 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlDoclet.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlDoclet.java @@ -313,7 +313,7 @@ public class HtmlDoclet extends AbstractDoclet { private void copyJqueryFiles() throws DocletException { List files = Arrays.asList( - "jquery-3.5.1.min.js", + "jquery-3.6.0.min.js", "jquery-ui.min.js", "jquery-ui.min.css", "jquery-ui.structure.min.css", diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlDocletWriter.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlDocletWriter.java index 8934d547213dcbca49476572c929ab29a31cf817..ac6d395cb25b761355ab0a61310acc131e95df29 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlDocletWriter.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlDocletWriter.java @@ -1010,6 +1010,10 @@ public class HtmlDocletWriter { // @see reference label... label = ref.subList(1, ref.size()); } + case ERRONEOUS -> { + return invalidTagOutput(resources.getText("doclet.tag.invalid_input", seeText), + Optional.empty()); + } default -> throw new IllegalStateException(ref.get(0).getKind().toString()); } @@ -2399,6 +2403,10 @@ public class HtmlDocletWriter { if (!utils.isIncluded(enclosed)) { continue; } + if (utils.isPreviewAPI(enclosed)) { + //for class summary, ignore methods that are themselves preview: + continue; + } if (!enclosed.getKind().isClass() && !enclosed.getKind().isInterface()) { PreviewSummary memberAPITypes = utils.declaredUsingPreviewAPIs(enclosed); declaredUsingPreviewFeature.addAll(memberAPITypes.declaredUsingPreviewFeature); diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlLinkFactory.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlLinkFactory.java index ee09e99cea6d93891f25aca562ce529c4d39a7cf..3956987baa9f8beeaaba1893aa4ae2554b6a189c 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlLinkFactory.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlLinkFactory.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 @@ -89,18 +89,29 @@ public class HtmlLinkFactory extends LinkFactory { } Content label = classLinkInfo.getClassLinkLabel(configuration); Set flags; - Element target; + Element previewTarget; boolean showPreview = !classLinkInfo.skipPreview; if (!hasWhere && showPreview) { flags = utils.elementFlags(typeElement); - target = typeElement; + previewTarget = typeElement; } else if ((classLinkInfo.context == HtmlLinkInfo.Kind.SEE_TAG || classLinkInfo.context == HtmlLinkInfo.Kind.MEMBER_DEPRECATED_PREVIEW) && classLinkInfo.targetMember != null && showPreview) { flags = utils.elementFlags(classLinkInfo.targetMember); - target = classLinkInfo.targetMember; + TypeElement enclosing = utils.getEnclosingTypeElement(classLinkInfo.targetMember); + Set enclosingFlags = utils.elementFlags(enclosing); + if (flags.contains(ElementFlag.PREVIEW) && enclosingFlags.contains(ElementFlag.PREVIEW)) { + if (enclosing.equals(m_writer.getCurrentPageElement())) { + //skip the PREVIEW tag: + flags = EnumSet.copyOf(flags); + flags.remove(ElementFlag.PREVIEW); + } + previewTarget = enclosing; + } else { + previewTarget = classLinkInfo.targetMember; + } } else { flags = EnumSet.noneOf(ElementFlag.class); - target = null; + previewTarget = null; } Content link = new ContentBuilder(); @@ -115,7 +126,7 @@ public class HtmlLinkFactory extends LinkFactory { title)); if (flags.contains(ElementFlag.PREVIEW)) { link.add(HtmlTree.SUP(m_writer.links.createLink( - filename.fragment(m_writer.htmlIds.forPreviewSection(target).name()), + filename.fragment(m_writer.htmlIds.forPreviewSection(previewTarget).name()), m_writer.contents.previewMark))); } return link; @@ -130,7 +141,7 @@ public class HtmlLinkFactory extends LinkFactory { if (flags.contains(ElementFlag.PREVIEW)) { link.add(HtmlTree.SUP(m_writer.getCrossClassLink( typeElement, - m_writer.htmlIds.forPreviewSection(target).name(), + m_writer.htmlIds.forPreviewSection(previewTarget).name(), m_writer.contents.previewMark, null, false))); } @@ -192,7 +203,7 @@ public class HtmlLinkFactory extends LinkFactory { */ protected Content getTypeParameterLink(LinkInfo linkInfo, TypeMirror typeParam) { HtmlLinkInfo typeLinkInfo = new HtmlLinkInfo(m_writer.configuration, - ((HtmlLinkInfo) linkInfo).getContext(), typeParam).skipPreview(true); + ((HtmlLinkInfo) linkInfo).getContext(), typeParam); typeLinkInfo.excludeTypeBounds = linkInfo.excludeTypeBounds; typeLinkInfo.excludeTypeParameterLinks = linkInfo.excludeTypeParameterLinks; typeLinkInfo.linkToSelf = linkInfo.linkToSelf; diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/TagletWriterImpl.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/TagletWriterImpl.java index fdac4e55576804f710f58c0fb964b124ca69fb03..adf98e0b8a0942c10524aca5bc002f94716d55fb 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/TagletWriterImpl.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/TagletWriterImpl.java @@ -76,6 +76,7 @@ import jdk.javadoc.internal.doclets.toolkit.util.DocPath; import jdk.javadoc.internal.doclets.toolkit.util.DocPaths; import jdk.javadoc.internal.doclets.toolkit.util.IndexItem; import jdk.javadoc.internal.doclets.toolkit.util.Utils; +import jdk.javadoc.internal.doclets.toolkit.util.Utils.PreviewFlagProvider; /** * The taglet writer that writes HTML. @@ -435,12 +436,18 @@ public class TagletWriterImpl extends TagletWriter { int idx = line.indexOf(strippedLine); assert idx >= 0; // because the stripped line is a substring of the line being stripped Text whitespace = Text.of(utils.normalizeNewlines(line.substring(0, idx))); - // If the leading whitespace is not excluded from the link, - // browsers might exhibit unwanted behavior. For example, a - // browser might display hand-click cursor while user hovers - // over that whitespace portion of the line; or use - // underline decoration. - c = new ContentBuilder(whitespace, htmlWriter.linkToContent(element, e, t, strippedLine)); + //disable preview tagging inside the snippets: + PreviewFlagProvider prevPreviewProvider = utils.setPreviewFlagProvider(el -> false); + try { + // If the leading whitespace is not excluded from the link, + // browsers might exhibit unwanted behavior. For example, a + // browser might display hand-click cursor while user hovers + // over that whitespace portion of the line; or use + // underline decoration. + c = new ContentBuilder(whitespace, htmlWriter.linkToContent(element, e, t, strippedLine)); + } finally { + utils.setPreviewFlagProvider(prevPreviewProvider); + } // We don't care about trailing whitespace. } else { c = HtmlTree.SPAN(Text.of(text)); diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/script-dir/jquery-3.5.1.min.js b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/script-dir/jquery-3.5.1.min.js deleted file mode 100644 index b0614034ad3a95e4ae9f53c2b015eeb3e8d68bde..0000000000000000000000000000000000000000 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/script-dir/jquery-3.5.1.min.js +++ /dev/null @@ -1,2 +0,0 @@ -/*! jQuery v3.5.1 | (c) JS Foundation and other contributors | jquery.org/license */ -!function(e,t){"use strict";"object"==typeof module&&"object"==typeof module.exports?module.exports=e.document?t(e,!0):function(e){if(!e.document)throw new Error("jQuery requires a window with a document");return t(e)}:t(e)}("undefined"!=typeof window?window:this,function(C,e){"use strict";var t=[],r=Object.getPrototypeOf,s=t.slice,g=t.flat?function(e){return t.flat.call(e)}:function(e){return t.concat.apply([],e)},u=t.push,i=t.indexOf,n={},o=n.toString,v=n.hasOwnProperty,a=v.toString,l=a.call(Object),y={},m=function(e){return"function"==typeof e&&"number"!=typeof e.nodeType},x=function(e){return null!=e&&e===e.window},E=C.document,c={type:!0,src:!0,nonce:!0,noModule:!0};function b(e,t,n){var r,i,o=(n=n||E).createElement("script");if(o.text=e,t)for(r in c)(i=t[r]||t.getAttribute&&t.getAttribute(r))&&o.setAttribute(r,i);n.head.appendChild(o).parentNode.removeChild(o)}function w(e){return null==e?e+"":"object"==typeof e||"function"==typeof e?n[o.call(e)]||"object":typeof e}var f="3.5.1",S=function(e,t){return new S.fn.init(e,t)};function p(e){var t=!!e&&"length"in e&&e.length,n=w(e);return!m(e)&&!x(e)&&("array"===n||0===t||"number"==typeof t&&0+~]|"+M+")"+M+"*"),U=new RegExp(M+"|>"),X=new RegExp(F),V=new RegExp("^"+I+"$"),G={ID:new RegExp("^#("+I+")"),CLASS:new RegExp("^\\.("+I+")"),TAG:new RegExp("^("+I+"|[*])"),ATTR:new RegExp("^"+W),PSEUDO:new RegExp("^"+F),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+M+"*(even|odd|(([+-]|)(\\d*)n|)"+M+"*(?:([+-]|)"+M+"*(\\d+)|))"+M+"*\\)|)","i"),bool:new RegExp("^(?:"+R+")$","i"),needsContext:new RegExp("^"+M+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+M+"*((?:-\\d)?\\d*)"+M+"*\\)|)(?=[^-]|$)","i")},Y=/HTML$/i,Q=/^(?:input|select|textarea|button)$/i,J=/^h\d$/i,K=/^[^{]+\{\s*\[native \w/,Z=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,ee=/[+~]/,te=new RegExp("\\\\[\\da-fA-F]{1,6}"+M+"?|\\\\([^\\r\\n\\f])","g"),ne=function(e,t){var n="0x"+e.slice(1)-65536;return t||(n<0?String.fromCharCode(n+65536):String.fromCharCode(n>>10|55296,1023&n|56320))},re=/([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g,ie=function(e,t){return t?"\0"===e?"\ufffd":e.slice(0,-1)+"\\"+e.charCodeAt(e.length-1).toString(16)+" ":"\\"+e},oe=function(){T()},ae=be(function(e){return!0===e.disabled&&"fieldset"===e.nodeName.toLowerCase()},{dir:"parentNode",next:"legend"});try{H.apply(t=O.call(p.childNodes),p.childNodes),t[p.childNodes.length].nodeType}catch(e){H={apply:t.length?function(e,t){L.apply(e,O.call(t))}:function(e,t){var n=e.length,r=0;while(e[n++]=t[r++]);e.length=n-1}}}function se(t,e,n,r){var i,o,a,s,u,l,c,f=e&&e.ownerDocument,p=e?e.nodeType:9;if(n=n||[],"string"!=typeof t||!t||1!==p&&9!==p&&11!==p)return n;if(!r&&(T(e),e=e||C,E)){if(11!==p&&(u=Z.exec(t)))if(i=u[1]){if(9===p){if(!(a=e.getElementById(i)))return n;if(a.id===i)return n.push(a),n}else if(f&&(a=f.getElementById(i))&&y(e,a)&&a.id===i)return n.push(a),n}else{if(u[2])return H.apply(n,e.getElementsByTagName(t)),n;if((i=u[3])&&d.getElementsByClassName&&e.getElementsByClassName)return H.apply(n,e.getElementsByClassName(i)),n}if(d.qsa&&!N[t+" "]&&(!v||!v.test(t))&&(1!==p||"object"!==e.nodeName.toLowerCase())){if(c=t,f=e,1===p&&(U.test(t)||z.test(t))){(f=ee.test(t)&&ye(e.parentNode)||e)===e&&d.scope||((s=e.getAttribute("id"))?s=s.replace(re,ie):e.setAttribute("id",s=S)),o=(l=h(t)).length;while(o--)l[o]=(s?"#"+s:":scope")+" "+xe(l[o]);c=l.join(",")}try{return H.apply(n,f.querySelectorAll(c)),n}catch(e){N(t,!0)}finally{s===S&&e.removeAttribute("id")}}}return g(t.replace($,"$1"),e,n,r)}function ue(){var r=[];return function e(t,n){return r.push(t+" ")>b.cacheLength&&delete e[r.shift()],e[t+" "]=n}}function le(e){return e[S]=!0,e}function ce(e){var t=C.createElement("fieldset");try{return!!e(t)}catch(e){return!1}finally{t.parentNode&&t.parentNode.removeChild(t),t=null}}function fe(e,t){var n=e.split("|"),r=n.length;while(r--)b.attrHandle[n[r]]=t}function pe(e,t){var n=t&&e,r=n&&1===e.nodeType&&1===t.nodeType&&e.sourceIndex-t.sourceIndex;if(r)return r;if(n)while(n=n.nextSibling)if(n===t)return-1;return e?1:-1}function de(t){return function(e){return"input"===e.nodeName.toLowerCase()&&e.type===t}}function he(n){return function(e){var t=e.nodeName.toLowerCase();return("input"===t||"button"===t)&&e.type===n}}function ge(t){return function(e){return"form"in e?e.parentNode&&!1===e.disabled?"label"in e?"label"in e.parentNode?e.parentNode.disabled===t:e.disabled===t:e.isDisabled===t||e.isDisabled!==!t&&ae(e)===t:e.disabled===t:"label"in e&&e.disabled===t}}function ve(a){return le(function(o){return o=+o,le(function(e,t){var n,r=a([],e.length,o),i=r.length;while(i--)e[n=r[i]]&&(e[n]=!(t[n]=e[n]))})})}function ye(e){return e&&"undefined"!=typeof e.getElementsByTagName&&e}for(e in d=se.support={},i=se.isXML=function(e){var t=e.namespaceURI,n=(e.ownerDocument||e).documentElement;return!Y.test(t||n&&n.nodeName||"HTML")},T=se.setDocument=function(e){var t,n,r=e?e.ownerDocument||e:p;return r!=C&&9===r.nodeType&&r.documentElement&&(a=(C=r).documentElement,E=!i(C),p!=C&&(n=C.defaultView)&&n.top!==n&&(n.addEventListener?n.addEventListener("unload",oe,!1):n.attachEvent&&n.attachEvent("onunload",oe)),d.scope=ce(function(e){return a.appendChild(e).appendChild(C.createElement("div")),"undefined"!=typeof e.querySelectorAll&&!e.querySelectorAll(":scope fieldset div").length}),d.attributes=ce(function(e){return e.className="i",!e.getAttribute("className")}),d.getElementsByTagName=ce(function(e){return e.appendChild(C.createComment("")),!e.getElementsByTagName("*").length}),d.getElementsByClassName=K.test(C.getElementsByClassName),d.getById=ce(function(e){return a.appendChild(e).id=S,!C.getElementsByName||!C.getElementsByName(S).length}),d.getById?(b.filter.ID=function(e){var t=e.replace(te,ne);return function(e){return e.getAttribute("id")===t}},b.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&E){var n=t.getElementById(e);return n?[n]:[]}}):(b.filter.ID=function(e){var n=e.replace(te,ne);return function(e){var t="undefined"!=typeof e.getAttributeNode&&e.getAttributeNode("id");return t&&t.value===n}},b.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&E){var n,r,i,o=t.getElementById(e);if(o){if((n=o.getAttributeNode("id"))&&n.value===e)return[o];i=t.getElementsByName(e),r=0;while(o=i[r++])if((n=o.getAttributeNode("id"))&&n.value===e)return[o]}return[]}}),b.find.TAG=d.getElementsByTagName?function(e,t){return"undefined"!=typeof t.getElementsByTagName?t.getElementsByTagName(e):d.qsa?t.querySelectorAll(e):void 0}:function(e,t){var n,r=[],i=0,o=t.getElementsByTagName(e);if("*"===e){while(n=o[i++])1===n.nodeType&&r.push(n);return r}return o},b.find.CLASS=d.getElementsByClassName&&function(e,t){if("undefined"!=typeof t.getElementsByClassName&&E)return t.getElementsByClassName(e)},s=[],v=[],(d.qsa=K.test(C.querySelectorAll))&&(ce(function(e){var t;a.appendChild(e).innerHTML="",e.querySelectorAll("[msallowcapture^='']").length&&v.push("[*^$]="+M+"*(?:''|\"\")"),e.querySelectorAll("[selected]").length||v.push("\\["+M+"*(?:value|"+R+")"),e.querySelectorAll("[id~="+S+"-]").length||v.push("~="),(t=C.createElement("input")).setAttribute("name",""),e.appendChild(t),e.querySelectorAll("[name='']").length||v.push("\\["+M+"*name"+M+"*="+M+"*(?:''|\"\")"),e.querySelectorAll(":checked").length||v.push(":checked"),e.querySelectorAll("a#"+S+"+*").length||v.push(".#.+[+~]"),e.querySelectorAll("\\\f"),v.push("[\\r\\n\\f]")}),ce(function(e){e.innerHTML="";var t=C.createElement("input");t.setAttribute("type","hidden"),e.appendChild(t).setAttribute("name","D"),e.querySelectorAll("[name=d]").length&&v.push("name"+M+"*[*^$|!~]?="),2!==e.querySelectorAll(":enabled").length&&v.push(":enabled",":disabled"),a.appendChild(e).disabled=!0,2!==e.querySelectorAll(":disabled").length&&v.push(":enabled",":disabled"),e.querySelectorAll("*,:x"),v.push(",.*:")})),(d.matchesSelector=K.test(c=a.matches||a.webkitMatchesSelector||a.mozMatchesSelector||a.oMatchesSelector||a.msMatchesSelector))&&ce(function(e){d.disconnectedMatch=c.call(e,"*"),c.call(e,"[s!='']:x"),s.push("!=",F)}),v=v.length&&new RegExp(v.join("|")),s=s.length&&new RegExp(s.join("|")),t=K.test(a.compareDocumentPosition),y=t||K.test(a.contains)?function(e,t){var n=9===e.nodeType?e.documentElement:e,r=t&&t.parentNode;return e===r||!(!r||1!==r.nodeType||!(n.contains?n.contains(r):e.compareDocumentPosition&&16&e.compareDocumentPosition(r)))}:function(e,t){if(t)while(t=t.parentNode)if(t===e)return!0;return!1},D=t?function(e,t){if(e===t)return l=!0,0;var n=!e.compareDocumentPosition-!t.compareDocumentPosition;return n||(1&(n=(e.ownerDocument||e)==(t.ownerDocument||t)?e.compareDocumentPosition(t):1)||!d.sortDetached&&t.compareDocumentPosition(e)===n?e==C||e.ownerDocument==p&&y(p,e)?-1:t==C||t.ownerDocument==p&&y(p,t)?1:u?P(u,e)-P(u,t):0:4&n?-1:1)}:function(e,t){if(e===t)return l=!0,0;var n,r=0,i=e.parentNode,o=t.parentNode,a=[e],s=[t];if(!i||!o)return e==C?-1:t==C?1:i?-1:o?1:u?P(u,e)-P(u,t):0;if(i===o)return pe(e,t);n=e;while(n=n.parentNode)a.unshift(n);n=t;while(n=n.parentNode)s.unshift(n);while(a[r]===s[r])r++;return r?pe(a[r],s[r]):a[r]==p?-1:s[r]==p?1:0}),C},se.matches=function(e,t){return se(e,null,null,t)},se.matchesSelector=function(e,t){if(T(e),d.matchesSelector&&E&&!N[t+" "]&&(!s||!s.test(t))&&(!v||!v.test(t)))try{var n=c.call(e,t);if(n||d.disconnectedMatch||e.document&&11!==e.document.nodeType)return n}catch(e){N(t,!0)}return 0":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace(te,ne),e[3]=(e[3]||e[4]||e[5]||"").replace(te,ne),"~="===e[2]&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),"nth"===e[1].slice(0,3)?(e[3]||se.error(e[0]),e[4]=+(e[4]?e[5]+(e[6]||1):2*("even"===e[3]||"odd"===e[3])),e[5]=+(e[7]+e[8]||"odd"===e[3])):e[3]&&se.error(e[0]),e},PSEUDO:function(e){var t,n=!e[6]&&e[2];return G.CHILD.test(e[0])?null:(e[3]?e[2]=e[4]||e[5]||"":n&&X.test(n)&&(t=h(n,!0))&&(t=n.indexOf(")",n.length-t)-n.length)&&(e[0]=e[0].slice(0,t),e[2]=n.slice(0,t)),e.slice(0,3))}},filter:{TAG:function(e){var t=e.replace(te,ne).toLowerCase();return"*"===e?function(){return!0}:function(e){return e.nodeName&&e.nodeName.toLowerCase()===t}},CLASS:function(e){var t=m[e+" "];return t||(t=new RegExp("(^|"+M+")"+e+"("+M+"|$)"))&&m(e,function(e){return t.test("string"==typeof e.className&&e.className||"undefined"!=typeof e.getAttribute&&e.getAttribute("class")||"")})},ATTR:function(n,r,i){return function(e){var t=se.attr(e,n);return null==t?"!="===r:!r||(t+="","="===r?t===i:"!="===r?t!==i:"^="===r?i&&0===t.indexOf(i):"*="===r?i&&-1:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i;function D(e,n,r){return m(n)?S.grep(e,function(e,t){return!!n.call(e,t,e)!==r}):n.nodeType?S.grep(e,function(e){return e===n!==r}):"string"!=typeof n?S.grep(e,function(e){return-1)[^>]*|#([\w-]+))$/;(S.fn.init=function(e,t,n){var r,i;if(!e)return this;if(n=n||j,"string"==typeof e){if(!(r="<"===e[0]&&">"===e[e.length-1]&&3<=e.length?[null,e,null]:q.exec(e))||!r[1]&&t)return!t||t.jquery?(t||n).find(e):this.constructor(t).find(e);if(r[1]){if(t=t instanceof S?t[0]:t,S.merge(this,S.parseHTML(r[1],t&&t.nodeType?t.ownerDocument||t:E,!0)),N.test(r[1])&&S.isPlainObject(t))for(r in t)m(this[r])?this[r](t[r]):this.attr(r,t[r]);return this}return(i=E.getElementById(r[2]))&&(this[0]=i,this.length=1),this}return e.nodeType?(this[0]=e,this.length=1,this):m(e)?void 0!==n.ready?n.ready(e):e(S):S.makeArray(e,this)}).prototype=S.fn,j=S(E);var L=/^(?:parents|prev(?:Until|All))/,H={children:!0,contents:!0,next:!0,prev:!0};function O(e,t){while((e=e[t])&&1!==e.nodeType);return e}S.fn.extend({has:function(e){var t=S(e,this),n=t.length;return this.filter(function(){for(var e=0;e\x20\t\r\n\f]*)/i,he=/^$|^module$|\/(?:java|ecma)script/i;ce=E.createDocumentFragment().appendChild(E.createElement("div")),(fe=E.createElement("input")).setAttribute("type","radio"),fe.setAttribute("checked","checked"),fe.setAttribute("name","t"),ce.appendChild(fe),y.checkClone=ce.cloneNode(!0).cloneNode(!0).lastChild.checked,ce.innerHTML="",y.noCloneChecked=!!ce.cloneNode(!0).lastChild.defaultValue,ce.innerHTML="",y.option=!!ce.lastChild;var ge={thead:[1,"","
"],col:[2,"","
"],tr:[2,"","
"],td:[3,"","
"],_default:[0,"",""]};function ve(e,t){var n;return n="undefined"!=typeof e.getElementsByTagName?e.getElementsByTagName(t||"*"):"undefined"!=typeof e.querySelectorAll?e.querySelectorAll(t||"*"):[],void 0===t||t&&A(e,t)?S.merge([e],n):n}function ye(e,t){for(var n=0,r=e.length;n",""]);var me=/<|&#?\w+;/;function xe(e,t,n,r,i){for(var o,a,s,u,l,c,f=t.createDocumentFragment(),p=[],d=0,h=e.length;d\s*$/g;function qe(e,t){return A(e,"table")&&A(11!==t.nodeType?t:t.firstChild,"tr")&&S(e).children("tbody")[0]||e}function Le(e){return e.type=(null!==e.getAttribute("type"))+"/"+e.type,e}function He(e){return"true/"===(e.type||"").slice(0,5)?e.type=e.type.slice(5):e.removeAttribute("type"),e}function Oe(e,t){var n,r,i,o,a,s;if(1===t.nodeType){if(Y.hasData(e)&&(s=Y.get(e).events))for(i in Y.remove(t,"handle events"),s)for(n=0,r=s[i].length;n").attr(n.scriptAttrs||{}).prop({charset:n.scriptCharset,src:n.url}).on("load error",i=function(e){r.remove(),i=null,e&&t("error"===e.type?404:200,e.type)}),E.head.appendChild(r[0])},abort:function(){i&&i()}}});var Ut,Xt=[],Vt=/(=)\?(?=&|$)|\?\?/;S.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var e=Xt.pop()||S.expando+"_"+Ct.guid++;return this[e]=!0,e}}),S.ajaxPrefilter("json jsonp",function(e,t,n){var r,i,o,a=!1!==e.jsonp&&(Vt.test(e.url)?"url":"string"==typeof e.data&&0===(e.contentType||"").indexOf("application/x-www-form-urlencoded")&&Vt.test(e.data)&&"data");if(a||"jsonp"===e.dataTypes[0])return r=e.jsonpCallback=m(e.jsonpCallback)?e.jsonpCallback():e.jsonpCallback,a?e[a]=e[a].replace(Vt,"$1"+r):!1!==e.jsonp&&(e.url+=(Et.test(e.url)?"&":"?")+e.jsonp+"="+r),e.converters["script json"]=function(){return o||S.error(r+" was not called"),o[0]},e.dataTypes[0]="json",i=C[r],C[r]=function(){o=arguments},n.always(function(){void 0===i?S(C).removeProp(r):C[r]=i,e[r]&&(e.jsonpCallback=t.jsonpCallback,Xt.push(r)),o&&m(i)&&i(o[0]),o=i=void 0}),"script"}),y.createHTMLDocument=((Ut=E.implementation.createHTMLDocument("").body).innerHTML="

",2===Ut.childNodes.length),S.parseHTML=function(e,t,n){return"string"!=typeof e?[]:("boolean"==typeof t&&(n=t,t=!1),t||(y.createHTMLDocument?((r=(t=E.implementation.createHTMLDocument("")).createElement("base")).href=E.location.href,t.head.appendChild(r)):t=E),o=!n&&[],(i=N.exec(e))?[t.createElement(i[1])]:(i=xe([e],t,o),o&&o.length&&S(o).remove(),S.merge([],i.childNodes)));var r,i,o},S.fn.load=function(e,t,n){var r,i,o,a=this,s=e.indexOf(" ");return-1").append(S.parseHTML(e)).find(r):e)}).always(n&&function(e,t){a.each(function(){n.apply(this,o||[e.responseText,t,e])})}),this},S.expr.pseudos.animated=function(t){return S.grep(S.timers,function(e){return t===e.elem}).length},S.offset={setOffset:function(e,t,n){var r,i,o,a,s,u,l=S.css(e,"position"),c=S(e),f={};"static"===l&&(e.style.position="relative"),s=c.offset(),o=S.css(e,"top"),u=S.css(e,"left"),("absolute"===l||"fixed"===l)&&-1<(o+u).indexOf("auto")?(a=(r=c.position()).top,i=r.left):(a=parseFloat(o)||0,i=parseFloat(u)||0),m(t)&&(t=t.call(e,n,S.extend({},s))),null!=t.top&&(f.top=t.top-s.top+a),null!=t.left&&(f.left=t.left-s.left+i),"using"in t?t.using.call(e,f):("number"==typeof f.top&&(f.top+="px"),"number"==typeof f.left&&(f.left+="px"),c.css(f))}},S.fn.extend({offset:function(t){if(arguments.length)return void 0===t?this:this.each(function(e){S.offset.setOffset(this,t,e)});var e,n,r=this[0];return r?r.getClientRects().length?(e=r.getBoundingClientRect(),n=r.ownerDocument.defaultView,{top:e.top+n.pageYOffset,left:e.left+n.pageXOffset}):{top:0,left:0}:void 0},position:function(){if(this[0]){var e,t,n,r=this[0],i={top:0,left:0};if("fixed"===S.css(r,"position"))t=r.getBoundingClientRect();else{t=this.offset(),n=r.ownerDocument,e=r.offsetParent||n.documentElement;while(e&&(e===n.body||e===n.documentElement)&&"static"===S.css(e,"position"))e=e.parentNode;e&&e!==r&&1===e.nodeType&&((i=S(e).offset()).top+=S.css(e,"borderTopWidth",!0),i.left+=S.css(e,"borderLeftWidth",!0))}return{top:t.top-i.top-S.css(r,"marginTop",!0),left:t.left-i.left-S.css(r,"marginLeft",!0)}}},offsetParent:function(){return this.map(function(){var e=this.offsetParent;while(e&&"static"===S.css(e,"position"))e=e.offsetParent;return e||re})}}),S.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(t,i){var o="pageYOffset"===i;S.fn[t]=function(e){return $(this,function(e,t,n){var r;if(x(e)?r=e:9===e.nodeType&&(r=e.defaultView),void 0===n)return r?r[i]:e[t];r?r.scrollTo(o?r.pageXOffset:n,o?n:r.pageYOffset):e[t]=n},t,e,arguments.length)}}),S.each(["top","left"],function(e,n){S.cssHooks[n]=$e(y.pixelPosition,function(e,t){if(t)return t=Be(e,n),Me.test(t)?S(e).position()[n]+"px":t})}),S.each({Height:"height",Width:"width"},function(a,s){S.each({padding:"inner"+a,content:s,"":"outer"+a},function(r,o){S.fn[o]=function(e,t){var n=arguments.length&&(r||"boolean"!=typeof e),i=r||(!0===e||!0===t?"margin":"border");return $(this,function(e,t,n){var r;return x(e)?0===o.indexOf("outer")?e["inner"+a]:e.document.documentElement["client"+a]:9===e.nodeType?(r=e.documentElement,Math.max(e.body["scroll"+a],r["scroll"+a],e.body["offset"+a],r["offset"+a],r["client"+a])):void 0===n?S.css(e,t,i):S.style(e,t,n,i)},s,n?e:void 0,n)}})}),S.each(["ajaxStart","ajaxStop","ajaxComplete","ajaxError","ajaxSuccess","ajaxSend"],function(e,t){S.fn[t]=function(e){return this.on(t,e)}}),S.fn.extend({bind:function(e,t,n){return this.on(e,null,t,n)},unbind:function(e,t){return this.off(e,null,t)},delegate:function(e,t,n,r){return this.on(t,e,n,r)},undelegate:function(e,t,n){return 1===arguments.length?this.off(e,"**"):this.off(t,e||"**",n)},hover:function(e,t){return this.mouseenter(e).mouseleave(t||e)}}),S.each("blur focus focusin focusout resize scroll click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup contextmenu".split(" "),function(e,n){S.fn[n]=function(e,t){return 0 elements - // (i.e., `typeof document.createElement( "object" ) === "function"`). - // We don't want to classify *any* DOM node as a function. - return typeof obj === "function" && typeof obj.nodeType !== "number"; - }; + // Support: Chrome <=57, Firefox <=52 + // In some browsers, typeof returns "function" for HTML elements + // (i.e., `typeof document.createElement( "object" ) === "function"`). + // We don't want to classify *any* DOM node as a function. + // Support: QtWeb <=3.8.5, WebKit <=534.34, wkhtmltopdf tool <=0.12.5 + // Plus for old WebKit, typeof returns "function" for HTML collections + // (e.g., `typeof document.getElementsByTagName("div") === "function"`). (gh-4756) + return typeof obj === "function" && typeof obj.nodeType !== "number" && + typeof obj.item !== "function"; + }; var isWindow = function isWindow( obj ) { @@ -147,7 +151,7 @@ function toType( obj ) { var - version = "3.5.1", + version = "3.6.0", // Define a local copy of jQuery jQuery = function( selector, context ) { @@ -401,7 +405,7 @@ jQuery.extend( { if ( isArrayLike( Object( arr ) ) ) { jQuery.merge( ret, typeof arr === "string" ? - [ arr ] : arr + [ arr ] : arr ); } else { push.call( ret, arr ); @@ -496,9 +500,9 @@ if ( typeof Symbol === "function" ) { // Populate the class2type map jQuery.each( "Boolean Number String Function Array Date RegExp Object Error Symbol".split( " " ), -function( _i, name ) { - class2type[ "[object " + name + "]" ] = name.toLowerCase(); -} ); + function( _i, name ) { + class2type[ "[object " + name + "]" ] = name.toLowerCase(); + } ); function isArrayLike( obj ) { @@ -518,14 +522,14 @@ function isArrayLike( obj ) { } var Sizzle = /*! - * Sizzle CSS Selector Engine v2.3.5 + * Sizzle CSS Selector Engine v2.3.6 * https://sizzlejs.com/ * * Copyright JS Foundation and other contributors * Released under the MIT license * https://js.foundation/ * - * Date: 2020-03-14 + * Date: 2021-02-16 */ ( function( window ) { var i, @@ -1108,8 +1112,8 @@ support = Sizzle.support = {}; * @returns {Boolean} True iff elem is a non-HTML XML node */ isXML = Sizzle.isXML = function( elem ) { - var namespace = elem.namespaceURI, - docElem = ( elem.ownerDocument || elem ).documentElement; + var namespace = elem && elem.namespaceURI, + docElem = elem && ( elem.ownerDocument || elem ).documentElement; // Support: IE <=8 // Assume HTML when documentElement doesn't yet exist, such as inside loading iframes @@ -3024,9 +3028,9 @@ var rneedsContext = jQuery.expr.match.needsContext; function nodeName( elem, name ) { - return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase(); + return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase(); -}; +} var rsingleTag = ( /^<([a-z][^\/\0>:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i ); @@ -3997,8 +4001,8 @@ jQuery.extend( { resolveContexts = Array( i ), resolveValues = slice.call( arguments ), - // the master Deferred - master = jQuery.Deferred(), + // the primary Deferred + primary = jQuery.Deferred(), // subordinate callback factory updateFunc = function( i ) { @@ -4006,30 +4010,30 @@ jQuery.extend( { resolveContexts[ i ] = this; resolveValues[ i ] = arguments.length > 1 ? slice.call( arguments ) : value; if ( !( --remaining ) ) { - master.resolveWith( resolveContexts, resolveValues ); + primary.resolveWith( resolveContexts, resolveValues ); } }; }; // Single- and empty arguments are adopted like Promise.resolve if ( remaining <= 1 ) { - adoptValue( singleValue, master.done( updateFunc( i ) ).resolve, master.reject, + adoptValue( singleValue, primary.done( updateFunc( i ) ).resolve, primary.reject, !remaining ); // Use .then() to unwrap secondary thenables (cf. gh-3000) - if ( master.state() === "pending" || + if ( primary.state() === "pending" || isFunction( resolveValues[ i ] && resolveValues[ i ].then ) ) { - return master.then(); + return primary.then(); } } // Multiple arguments are aggregated like Promise.all array elements while ( i-- ) { - adoptValue( resolveValues[ i ], updateFunc( i ), master.reject ); + adoptValue( resolveValues[ i ], updateFunc( i ), primary.reject ); } - return master.promise(); + return primary.promise(); } } ); @@ -4180,8 +4184,8 @@ var access = function( elems, fn, key, value, chainable, emptyGet, raw ) { for ( ; i < len; i++ ) { fn( elems[ i ], key, raw ? - value : - value.call( elems[ i ], i, fn( elems[ i ], key ) ) + value : + value.call( elems[ i ], i, fn( elems[ i ], key ) ) ); } } @@ -5089,10 +5093,7 @@ function buildFragment( elems, context, scripts, selection, ignored ) { } -var - rkeyEvent = /^key/, - rmouseEvent = /^(?:mouse|pointer|contextmenu|drag|drop)|click/, - rtypenamespace = /^([^.]*)(?:\.(.+)|)/; +var rtypenamespace = /^([^.]*)(?:\.(.+)|)/; function returnTrue() { return true; @@ -5387,8 +5388,8 @@ jQuery.event = { event = jQuery.event.fix( nativeEvent ), handlers = ( - dataPriv.get( this, "events" ) || Object.create( null ) - )[ event.type ] || [], + dataPriv.get( this, "events" ) || Object.create( null ) + )[ event.type ] || [], special = jQuery.event.special[ event.type ] || {}; // Use the fix-ed jQuery.Event rather than the (read-only) native event @@ -5512,12 +5513,12 @@ jQuery.event = { get: isFunction( hook ) ? function() { if ( this.originalEvent ) { - return hook( this.originalEvent ); + return hook( this.originalEvent ); } } : function() { if ( this.originalEvent ) { - return this.originalEvent[ name ]; + return this.originalEvent[ name ]; } }, @@ -5656,7 +5657,13 @@ function leverageNative( el, type, expectSync ) { // Cancel the outer synthetic event event.stopImmediatePropagation(); event.preventDefault(); - return result.value; + + // Support: Chrome 86+ + // In Chrome, if an element having a focusout handler is blurred by + // clicking outside of it, it invokes the handler synchronously. If + // that handler calls `.remove()` on the element, the data is cleared, + // leaving `result` undefined. We need to guard against this. + return result && result.value; } // If this is an inner synthetic event for an event with a bubbling surrogate @@ -5821,34 +5828,7 @@ jQuery.each( { targetTouches: true, toElement: true, touches: true, - - which: function( event ) { - var button = event.button; - - // Add which for key events - if ( event.which == null && rkeyEvent.test( event.type ) ) { - return event.charCode != null ? event.charCode : event.keyCode; - } - - // Add which for click: 1 === left; 2 === middle; 3 === right - if ( !event.which && button !== undefined && rmouseEvent.test( event.type ) ) { - if ( button & 1 ) { - return 1; - } - - if ( button & 2 ) { - return 3; - } - - if ( button & 4 ) { - return 2; - } - - return 0; - } - - return event.which; - } + which: true }, jQuery.event.addProp ); jQuery.each( { focus: "focusin", blur: "focusout" }, function( type, delegateType ) { @@ -5874,6 +5854,12 @@ jQuery.each( { focus: "focusin", blur: "focusout" }, function( type, delegateTyp return true; }, + // Suppress native focus or blur as it's already being fired + // in leverageNative. + _default: function() { + return true; + }, + delegateType: delegateType }; } ); @@ -6541,6 +6527,10 @@ var rboxStyle = new RegExp( cssExpand.join( "|" ), "i" ); // set in CSS while `offset*` properties report correct values. // Behavior in IE 9 is more subtle than in newer versions & it passes // some versions of this test; make sure not to make it pass there! + // + // Support: Firefox 70+ + // Only Firefox includes border widths + // in computed dimensions. (gh-4529) reliableTrDimensions: function() { var table, tr, trChild, trStyle; if ( reliableTrDimensionsVal == null ) { @@ -6548,17 +6538,32 @@ var rboxStyle = new RegExp( cssExpand.join( "|" ), "i" ); tr = document.createElement( "tr" ); trChild = document.createElement( "div" ); - table.style.cssText = "position:absolute;left:-11111px"; + table.style.cssText = "position:absolute;left:-11111px;border-collapse:separate"; + tr.style.cssText = "border:1px solid"; + + // Support: Chrome 86+ + // Height set through cssText does not get applied. + // Computed height then comes back as 0. tr.style.height = "1px"; trChild.style.height = "9px"; + // Support: Android 8 Chrome 86+ + // In our bodyBackground.html iframe, + // display for all div elements is set to "inline", + // which causes a problem only in Android 8 Chrome 86. + // Ensuring the div is display: block + // gets around this issue. + trChild.style.display = "block"; + documentElement .appendChild( table ) .appendChild( tr ) .appendChild( trChild ); trStyle = window.getComputedStyle( tr ); - reliableTrDimensionsVal = parseInt( trStyle.height ) > 3; + reliableTrDimensionsVal = ( parseInt( trStyle.height, 10 ) + + parseInt( trStyle.borderTopWidth, 10 ) + + parseInt( trStyle.borderBottomWidth, 10 ) ) === tr.offsetHeight; documentElement.removeChild( table ); } @@ -7022,10 +7027,10 @@ jQuery.each( [ "height", "width" ], function( _i, dimension ) { // Running getBoundingClientRect on a disconnected node // in IE throws an error. ( !elem.getClientRects().length || !elem.getBoundingClientRect().width ) ? - swap( elem, cssShow, function() { - return getWidthOrHeight( elem, dimension, extra ); - } ) : - getWidthOrHeight( elem, dimension, extra ); + swap( elem, cssShow, function() { + return getWidthOrHeight( elem, dimension, extra ); + } ) : + getWidthOrHeight( elem, dimension, extra ); } }, @@ -7084,7 +7089,7 @@ jQuery.cssHooks.marginLeft = addGetHookIf( support.reliableMarginLeft, swap( elem, { marginLeft: 0 }, function() { return elem.getBoundingClientRect().left; } ) - ) + "px"; + ) + "px"; } } ); @@ -7223,7 +7228,7 @@ Tween.propHooks = { if ( jQuery.fx.step[ tween.prop ] ) { jQuery.fx.step[ tween.prop ]( tween ); } else if ( tween.elem.nodeType === 1 && ( - jQuery.cssHooks[ tween.prop ] || + jQuery.cssHooks[ tween.prop ] || tween.elem.style[ finalPropName( tween.prop ) ] != null ) ) { jQuery.style( tween.elem, tween.prop, tween.now + tween.unit ); } else { @@ -7468,7 +7473,7 @@ function defaultPrefilter( elem, props, opts ) { anim.done( function() { - /* eslint-enable no-loop-func */ + /* eslint-enable no-loop-func */ // The final step of a "hide" animation is actually hiding the element if ( !hidden ) { @@ -7588,7 +7593,7 @@ function Animation( elem, properties, options ) { tweens: [], createTween: function( prop, end ) { var tween = jQuery.Tween( elem, animation.opts, prop, end, - animation.opts.specialEasing[ prop ] || animation.opts.easing ); + animation.opts.specialEasing[ prop ] || animation.opts.easing ); animation.tweens.push( tween ); return tween; }, @@ -7761,7 +7766,8 @@ jQuery.fn.extend( { anim.stop( true ); } }; - doAnimation.finish = doAnimation; + + doAnimation.finish = doAnimation; return empty || optall.queue === false ? this.each( doAnimation ) : @@ -8401,8 +8407,8 @@ jQuery.fn.extend( { if ( this.setAttribute ) { this.setAttribute( "class", className || value === false ? - "" : - dataPriv.get( this, "__className__" ) || "" + "" : + dataPriv.get( this, "__className__" ) || "" ); } } @@ -8417,7 +8423,7 @@ jQuery.fn.extend( { while ( ( elem = this[ i++ ] ) ) { if ( elem.nodeType === 1 && ( " " + stripAndCollapse( getClass( elem ) ) + " " ).indexOf( className ) > -1 ) { - return true; + return true; } } @@ -8707,9 +8713,7 @@ jQuery.extend( jQuery.event, { special.bindType || type; // jQuery handler - handle = ( - dataPriv.get( cur, "events" ) || Object.create( null ) - )[ event.type ] && + handle = ( dataPriv.get( cur, "events" ) || Object.create( null ) )[ event.type ] && dataPriv.get( cur, "handle" ); if ( handle ) { handle.apply( cur, data ); @@ -8856,7 +8860,7 @@ var rquery = ( /\?/ ); // Cross-browser xml parsing jQuery.parseXML = function( data ) { - var xml; + var xml, parserErrorElem; if ( !data || typeof data !== "string" ) { return null; } @@ -8865,12 +8869,17 @@ jQuery.parseXML = function( data ) { // IE throws on parseFromString with invalid input. try { xml = ( new window.DOMParser() ).parseFromString( data, "text/xml" ); - } catch ( e ) { - xml = undefined; - } + } catch ( e ) {} - if ( !xml || xml.getElementsByTagName( "parsererror" ).length ) { - jQuery.error( "Invalid XML: " + data ); + parserErrorElem = xml && xml.getElementsByTagName( "parsererror" )[ 0 ]; + if ( !xml || parserErrorElem ) { + jQuery.error( "Invalid XML: " + ( + parserErrorElem ? + jQuery.map( parserErrorElem.childNodes, function( el ) { + return el.textContent; + } ).join( "\n" ) : + data + ) ); } return xml; }; @@ -8971,16 +8980,14 @@ jQuery.fn.extend( { // Can add propHook for "elements" to filter or add form elements var elements = jQuery.prop( this, "elements" ); return elements ? jQuery.makeArray( elements ) : this; - } ) - .filter( function() { + } ).filter( function() { var type = this.type; // Use .is( ":disabled" ) so that fieldset[disabled] works return this.name && !jQuery( this ).is( ":disabled" ) && rsubmittable.test( this.nodeName ) && !rsubmitterTypes.test( type ) && ( this.checked || !rcheckableType.test( type ) ); - } ) - .map( function( _i, elem ) { + } ).map( function( _i, elem ) { var val = jQuery( this ).val(); if ( val == null ) { @@ -9033,7 +9040,8 @@ var // Anchor tag for parsing the document origin originAnchor = document.createElement( "a" ); - originAnchor.href = location.href; + +originAnchor.href = location.href; // Base "constructor" for jQuery.ajaxPrefilter and jQuery.ajaxTransport function addToPrefiltersOrTransports( structure ) { @@ -9414,8 +9422,8 @@ jQuery.extend( { // Context for global events is callbackContext if it is a DOM node or jQuery collection globalEventContext = s.context && ( callbackContext.nodeType || callbackContext.jquery ) ? - jQuery( callbackContext ) : - jQuery.event, + jQuery( callbackContext ) : + jQuery.event, // Deferreds deferred = jQuery.Deferred(), @@ -9727,8 +9735,10 @@ jQuery.extend( { response = ajaxHandleResponses( s, jqXHR, responses ); } - // Use a noop converter for missing script - if ( !isSuccess && jQuery.inArray( "script", s.dataTypes ) > -1 ) { + // Use a noop converter for missing script but not if jsonp + if ( !isSuccess && + jQuery.inArray( "script", s.dataTypes ) > -1 && + jQuery.inArray( "json", s.dataTypes ) < 0 ) { s.converters[ "text script" ] = function() {}; } @@ -10466,12 +10476,6 @@ jQuery.offset = { options.using.call( elem, props ); } else { - if ( typeof props.top === "number" ) { - props.top += "px"; - } - if ( typeof props.left === "number" ) { - props.left += "px"; - } curElem.css( props ); } } @@ -10640,8 +10644,11 @@ jQuery.each( [ "top", "left" ], function( _i, prop ) { // Create innerHeight, innerWidth, height, width, outerHeight and outerWidth methods jQuery.each( { Height: "height", Width: "width" }, function( name, type ) { - jQuery.each( { padding: "inner" + name, content: type, "": "outer" + name }, - function( defaultExtra, funcName ) { + jQuery.each( { + padding: "inner" + name, + content: type, + "": "outer" + name + }, function( defaultExtra, funcName ) { // Margin is only for outerHeight, outerWidth jQuery.fn[ funcName ] = function( margin, value ) { @@ -10726,7 +10733,8 @@ jQuery.fn.extend( { } } ); -jQuery.each( ( "blur focus focusin focusout resize scroll click dblclick " + +jQuery.each( + ( "blur focus focusin focusout resize scroll click dblclick " + "mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " + "change select submit keydown keypress keyup contextmenu" ).split( " " ), function( _i, name ) { @@ -10737,7 +10745,8 @@ jQuery.each( ( "blur focus focusin focusout resize scroll click dblclick " + this.on( name, null, data, fn ) : this.trigger( name ); }; - } ); + } +); diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/script-dir/jquery-3.6.0.min.js b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/script-dir/jquery-3.6.0.min.js new file mode 100644 index 0000000000000000000000000000000000000000..c4c6022f2982e8dae64cebd6b9a2b59f2547faad --- /dev/null +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/script-dir/jquery-3.6.0.min.js @@ -0,0 +1,2 @@ +/*! jQuery v3.6.0 | (c) OpenJS Foundation and other contributors | jquery.org/license */ +!function(e,t){"use strict";"object"==typeof module&&"object"==typeof module.exports?module.exports=e.document?t(e,!0):function(e){if(!e.document)throw new Error("jQuery requires a window with a document");return t(e)}:t(e)}("undefined"!=typeof window?window:this,function(C,e){"use strict";var t=[],r=Object.getPrototypeOf,s=t.slice,g=t.flat?function(e){return t.flat.call(e)}:function(e){return t.concat.apply([],e)},u=t.push,i=t.indexOf,n={},o=n.toString,v=n.hasOwnProperty,a=v.toString,l=a.call(Object),y={},m=function(e){return"function"==typeof e&&"number"!=typeof e.nodeType&&"function"!=typeof e.item},x=function(e){return null!=e&&e===e.window},E=C.document,c={type:!0,src:!0,nonce:!0,noModule:!0};function b(e,t,n){var r,i,o=(n=n||E).createElement("script");if(o.text=e,t)for(r in c)(i=t[r]||t.getAttribute&&t.getAttribute(r))&&o.setAttribute(r,i);n.head.appendChild(o).parentNode.removeChild(o)}function w(e){return null==e?e+"":"object"==typeof e||"function"==typeof e?n[o.call(e)]||"object":typeof e}var f="3.6.0",S=function(e,t){return new S.fn.init(e,t)};function p(e){var t=!!e&&"length"in e&&e.length,n=w(e);return!m(e)&&!x(e)&&("array"===n||0===t||"number"==typeof t&&0+~]|"+M+")"+M+"*"),U=new RegExp(M+"|>"),X=new RegExp(F),V=new RegExp("^"+I+"$"),G={ID:new RegExp("^#("+I+")"),CLASS:new RegExp("^\\.("+I+")"),TAG:new RegExp("^("+I+"|[*])"),ATTR:new RegExp("^"+W),PSEUDO:new RegExp("^"+F),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+M+"*(even|odd|(([+-]|)(\\d*)n|)"+M+"*(?:([+-]|)"+M+"*(\\d+)|))"+M+"*\\)|)","i"),bool:new RegExp("^(?:"+R+")$","i"),needsContext:new RegExp("^"+M+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+M+"*((?:-\\d)?\\d*)"+M+"*\\)|)(?=[^-]|$)","i")},Y=/HTML$/i,Q=/^(?:input|select|textarea|button)$/i,J=/^h\d$/i,K=/^[^{]+\{\s*\[native \w/,Z=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,ee=/[+~]/,te=new RegExp("\\\\[\\da-fA-F]{1,6}"+M+"?|\\\\([^\\r\\n\\f])","g"),ne=function(e,t){var n="0x"+e.slice(1)-65536;return t||(n<0?String.fromCharCode(n+65536):String.fromCharCode(n>>10|55296,1023&n|56320))},re=/([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g,ie=function(e,t){return t?"\0"===e?"\ufffd":e.slice(0,-1)+"\\"+e.charCodeAt(e.length-1).toString(16)+" ":"\\"+e},oe=function(){T()},ae=be(function(e){return!0===e.disabled&&"fieldset"===e.nodeName.toLowerCase()},{dir:"parentNode",next:"legend"});try{H.apply(t=O.call(p.childNodes),p.childNodes),t[p.childNodes.length].nodeType}catch(e){H={apply:t.length?function(e,t){L.apply(e,O.call(t))}:function(e,t){var n=e.length,r=0;while(e[n++]=t[r++]);e.length=n-1}}}function se(t,e,n,r){var i,o,a,s,u,l,c,f=e&&e.ownerDocument,p=e?e.nodeType:9;if(n=n||[],"string"!=typeof t||!t||1!==p&&9!==p&&11!==p)return n;if(!r&&(T(e),e=e||C,E)){if(11!==p&&(u=Z.exec(t)))if(i=u[1]){if(9===p){if(!(a=e.getElementById(i)))return n;if(a.id===i)return n.push(a),n}else if(f&&(a=f.getElementById(i))&&y(e,a)&&a.id===i)return n.push(a),n}else{if(u[2])return H.apply(n,e.getElementsByTagName(t)),n;if((i=u[3])&&d.getElementsByClassName&&e.getElementsByClassName)return H.apply(n,e.getElementsByClassName(i)),n}if(d.qsa&&!N[t+" "]&&(!v||!v.test(t))&&(1!==p||"object"!==e.nodeName.toLowerCase())){if(c=t,f=e,1===p&&(U.test(t)||z.test(t))){(f=ee.test(t)&&ye(e.parentNode)||e)===e&&d.scope||((s=e.getAttribute("id"))?s=s.replace(re,ie):e.setAttribute("id",s=S)),o=(l=h(t)).length;while(o--)l[o]=(s?"#"+s:":scope")+" "+xe(l[o]);c=l.join(",")}try{return H.apply(n,f.querySelectorAll(c)),n}catch(e){N(t,!0)}finally{s===S&&e.removeAttribute("id")}}}return g(t.replace($,"$1"),e,n,r)}function ue(){var r=[];return function e(t,n){return r.push(t+" ")>b.cacheLength&&delete e[r.shift()],e[t+" "]=n}}function le(e){return e[S]=!0,e}function ce(e){var t=C.createElement("fieldset");try{return!!e(t)}catch(e){return!1}finally{t.parentNode&&t.parentNode.removeChild(t),t=null}}function fe(e,t){var n=e.split("|"),r=n.length;while(r--)b.attrHandle[n[r]]=t}function pe(e,t){var n=t&&e,r=n&&1===e.nodeType&&1===t.nodeType&&e.sourceIndex-t.sourceIndex;if(r)return r;if(n)while(n=n.nextSibling)if(n===t)return-1;return e?1:-1}function de(t){return function(e){return"input"===e.nodeName.toLowerCase()&&e.type===t}}function he(n){return function(e){var t=e.nodeName.toLowerCase();return("input"===t||"button"===t)&&e.type===n}}function ge(t){return function(e){return"form"in e?e.parentNode&&!1===e.disabled?"label"in e?"label"in e.parentNode?e.parentNode.disabled===t:e.disabled===t:e.isDisabled===t||e.isDisabled!==!t&&ae(e)===t:e.disabled===t:"label"in e&&e.disabled===t}}function ve(a){return le(function(o){return o=+o,le(function(e,t){var n,r=a([],e.length,o),i=r.length;while(i--)e[n=r[i]]&&(e[n]=!(t[n]=e[n]))})})}function ye(e){return e&&"undefined"!=typeof e.getElementsByTagName&&e}for(e in d=se.support={},i=se.isXML=function(e){var t=e&&e.namespaceURI,n=e&&(e.ownerDocument||e).documentElement;return!Y.test(t||n&&n.nodeName||"HTML")},T=se.setDocument=function(e){var t,n,r=e?e.ownerDocument||e:p;return r!=C&&9===r.nodeType&&r.documentElement&&(a=(C=r).documentElement,E=!i(C),p!=C&&(n=C.defaultView)&&n.top!==n&&(n.addEventListener?n.addEventListener("unload",oe,!1):n.attachEvent&&n.attachEvent("onunload",oe)),d.scope=ce(function(e){return a.appendChild(e).appendChild(C.createElement("div")),"undefined"!=typeof e.querySelectorAll&&!e.querySelectorAll(":scope fieldset div").length}),d.attributes=ce(function(e){return e.className="i",!e.getAttribute("className")}),d.getElementsByTagName=ce(function(e){return e.appendChild(C.createComment("")),!e.getElementsByTagName("*").length}),d.getElementsByClassName=K.test(C.getElementsByClassName),d.getById=ce(function(e){return a.appendChild(e).id=S,!C.getElementsByName||!C.getElementsByName(S).length}),d.getById?(b.filter.ID=function(e){var t=e.replace(te,ne);return function(e){return e.getAttribute("id")===t}},b.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&E){var n=t.getElementById(e);return n?[n]:[]}}):(b.filter.ID=function(e){var n=e.replace(te,ne);return function(e){var t="undefined"!=typeof e.getAttributeNode&&e.getAttributeNode("id");return t&&t.value===n}},b.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&E){var n,r,i,o=t.getElementById(e);if(o){if((n=o.getAttributeNode("id"))&&n.value===e)return[o];i=t.getElementsByName(e),r=0;while(o=i[r++])if((n=o.getAttributeNode("id"))&&n.value===e)return[o]}return[]}}),b.find.TAG=d.getElementsByTagName?function(e,t){return"undefined"!=typeof t.getElementsByTagName?t.getElementsByTagName(e):d.qsa?t.querySelectorAll(e):void 0}:function(e,t){var n,r=[],i=0,o=t.getElementsByTagName(e);if("*"===e){while(n=o[i++])1===n.nodeType&&r.push(n);return r}return o},b.find.CLASS=d.getElementsByClassName&&function(e,t){if("undefined"!=typeof t.getElementsByClassName&&E)return t.getElementsByClassName(e)},s=[],v=[],(d.qsa=K.test(C.querySelectorAll))&&(ce(function(e){var t;a.appendChild(e).innerHTML="",e.querySelectorAll("[msallowcapture^='']").length&&v.push("[*^$]="+M+"*(?:''|\"\")"),e.querySelectorAll("[selected]").length||v.push("\\["+M+"*(?:value|"+R+")"),e.querySelectorAll("[id~="+S+"-]").length||v.push("~="),(t=C.createElement("input")).setAttribute("name",""),e.appendChild(t),e.querySelectorAll("[name='']").length||v.push("\\["+M+"*name"+M+"*="+M+"*(?:''|\"\")"),e.querySelectorAll(":checked").length||v.push(":checked"),e.querySelectorAll("a#"+S+"+*").length||v.push(".#.+[+~]"),e.querySelectorAll("\\\f"),v.push("[\\r\\n\\f]")}),ce(function(e){e.innerHTML="";var t=C.createElement("input");t.setAttribute("type","hidden"),e.appendChild(t).setAttribute("name","D"),e.querySelectorAll("[name=d]").length&&v.push("name"+M+"*[*^$|!~]?="),2!==e.querySelectorAll(":enabled").length&&v.push(":enabled",":disabled"),a.appendChild(e).disabled=!0,2!==e.querySelectorAll(":disabled").length&&v.push(":enabled",":disabled"),e.querySelectorAll("*,:x"),v.push(",.*:")})),(d.matchesSelector=K.test(c=a.matches||a.webkitMatchesSelector||a.mozMatchesSelector||a.oMatchesSelector||a.msMatchesSelector))&&ce(function(e){d.disconnectedMatch=c.call(e,"*"),c.call(e,"[s!='']:x"),s.push("!=",F)}),v=v.length&&new RegExp(v.join("|")),s=s.length&&new RegExp(s.join("|")),t=K.test(a.compareDocumentPosition),y=t||K.test(a.contains)?function(e,t){var n=9===e.nodeType?e.documentElement:e,r=t&&t.parentNode;return e===r||!(!r||1!==r.nodeType||!(n.contains?n.contains(r):e.compareDocumentPosition&&16&e.compareDocumentPosition(r)))}:function(e,t){if(t)while(t=t.parentNode)if(t===e)return!0;return!1},j=t?function(e,t){if(e===t)return l=!0,0;var n=!e.compareDocumentPosition-!t.compareDocumentPosition;return n||(1&(n=(e.ownerDocument||e)==(t.ownerDocument||t)?e.compareDocumentPosition(t):1)||!d.sortDetached&&t.compareDocumentPosition(e)===n?e==C||e.ownerDocument==p&&y(p,e)?-1:t==C||t.ownerDocument==p&&y(p,t)?1:u?P(u,e)-P(u,t):0:4&n?-1:1)}:function(e,t){if(e===t)return l=!0,0;var n,r=0,i=e.parentNode,o=t.parentNode,a=[e],s=[t];if(!i||!o)return e==C?-1:t==C?1:i?-1:o?1:u?P(u,e)-P(u,t):0;if(i===o)return pe(e,t);n=e;while(n=n.parentNode)a.unshift(n);n=t;while(n=n.parentNode)s.unshift(n);while(a[r]===s[r])r++;return r?pe(a[r],s[r]):a[r]==p?-1:s[r]==p?1:0}),C},se.matches=function(e,t){return se(e,null,null,t)},se.matchesSelector=function(e,t){if(T(e),d.matchesSelector&&E&&!N[t+" "]&&(!s||!s.test(t))&&(!v||!v.test(t)))try{var n=c.call(e,t);if(n||d.disconnectedMatch||e.document&&11!==e.document.nodeType)return n}catch(e){N(t,!0)}return 0":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace(te,ne),e[3]=(e[3]||e[4]||e[5]||"").replace(te,ne),"~="===e[2]&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),"nth"===e[1].slice(0,3)?(e[3]||se.error(e[0]),e[4]=+(e[4]?e[5]+(e[6]||1):2*("even"===e[3]||"odd"===e[3])),e[5]=+(e[7]+e[8]||"odd"===e[3])):e[3]&&se.error(e[0]),e},PSEUDO:function(e){var t,n=!e[6]&&e[2];return G.CHILD.test(e[0])?null:(e[3]?e[2]=e[4]||e[5]||"":n&&X.test(n)&&(t=h(n,!0))&&(t=n.indexOf(")",n.length-t)-n.length)&&(e[0]=e[0].slice(0,t),e[2]=n.slice(0,t)),e.slice(0,3))}},filter:{TAG:function(e){var t=e.replace(te,ne).toLowerCase();return"*"===e?function(){return!0}:function(e){return e.nodeName&&e.nodeName.toLowerCase()===t}},CLASS:function(e){var t=m[e+" "];return t||(t=new RegExp("(^|"+M+")"+e+"("+M+"|$)"))&&m(e,function(e){return t.test("string"==typeof e.className&&e.className||"undefined"!=typeof e.getAttribute&&e.getAttribute("class")||"")})},ATTR:function(n,r,i){return function(e){var t=se.attr(e,n);return null==t?"!="===r:!r||(t+="","="===r?t===i:"!="===r?t!==i:"^="===r?i&&0===t.indexOf(i):"*="===r?i&&-1:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i;function j(e,n,r){return m(n)?S.grep(e,function(e,t){return!!n.call(e,t,e)!==r}):n.nodeType?S.grep(e,function(e){return e===n!==r}):"string"!=typeof n?S.grep(e,function(e){return-1)[^>]*|#([\w-]+))$/;(S.fn.init=function(e,t,n){var r,i;if(!e)return this;if(n=n||D,"string"==typeof e){if(!(r="<"===e[0]&&">"===e[e.length-1]&&3<=e.length?[null,e,null]:q.exec(e))||!r[1]&&t)return!t||t.jquery?(t||n).find(e):this.constructor(t).find(e);if(r[1]){if(t=t instanceof S?t[0]:t,S.merge(this,S.parseHTML(r[1],t&&t.nodeType?t.ownerDocument||t:E,!0)),N.test(r[1])&&S.isPlainObject(t))for(r in t)m(this[r])?this[r](t[r]):this.attr(r,t[r]);return this}return(i=E.getElementById(r[2]))&&(this[0]=i,this.length=1),this}return e.nodeType?(this[0]=e,this.length=1,this):m(e)?void 0!==n.ready?n.ready(e):e(S):S.makeArray(e,this)}).prototype=S.fn,D=S(E);var L=/^(?:parents|prev(?:Until|All))/,H={children:!0,contents:!0,next:!0,prev:!0};function O(e,t){while((e=e[t])&&1!==e.nodeType);return e}S.fn.extend({has:function(e){var t=S(e,this),n=t.length;return this.filter(function(){for(var e=0;e\x20\t\r\n\f]*)/i,he=/^$|^module$|\/(?:java|ecma)script/i;ce=E.createDocumentFragment().appendChild(E.createElement("div")),(fe=E.createElement("input")).setAttribute("type","radio"),fe.setAttribute("checked","checked"),fe.setAttribute("name","t"),ce.appendChild(fe),y.checkClone=ce.cloneNode(!0).cloneNode(!0).lastChild.checked,ce.innerHTML="",y.noCloneChecked=!!ce.cloneNode(!0).lastChild.defaultValue,ce.innerHTML="",y.option=!!ce.lastChild;var ge={thead:[1,"","
"],col:[2,"","
"],tr:[2,"","
"],td:[3,"","
"],_default:[0,"",""]};function ve(e,t){var n;return n="undefined"!=typeof e.getElementsByTagName?e.getElementsByTagName(t||"*"):"undefined"!=typeof e.querySelectorAll?e.querySelectorAll(t||"*"):[],void 0===t||t&&A(e,t)?S.merge([e],n):n}function ye(e,t){for(var n=0,r=e.length;n",""]);var me=/<|&#?\w+;/;function xe(e,t,n,r,i){for(var o,a,s,u,l,c,f=t.createDocumentFragment(),p=[],d=0,h=e.length;d\s*$/g;function je(e,t){return A(e,"table")&&A(11!==t.nodeType?t:t.firstChild,"tr")&&S(e).children("tbody")[0]||e}function De(e){return e.type=(null!==e.getAttribute("type"))+"/"+e.type,e}function qe(e){return"true/"===(e.type||"").slice(0,5)?e.type=e.type.slice(5):e.removeAttribute("type"),e}function Le(e,t){var n,r,i,o,a,s;if(1===t.nodeType){if(Y.hasData(e)&&(s=Y.get(e).events))for(i in Y.remove(t,"handle events"),s)for(n=0,r=s[i].length;n").attr(n.scriptAttrs||{}).prop({charset:n.scriptCharset,src:n.url}).on("load error",i=function(e){r.remove(),i=null,e&&t("error"===e.type?404:200,e.type)}),E.head.appendChild(r[0])},abort:function(){i&&i()}}});var _t,zt=[],Ut=/(=)\?(?=&|$)|\?\?/;S.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var e=zt.pop()||S.expando+"_"+wt.guid++;return this[e]=!0,e}}),S.ajaxPrefilter("json jsonp",function(e,t,n){var r,i,o,a=!1!==e.jsonp&&(Ut.test(e.url)?"url":"string"==typeof e.data&&0===(e.contentType||"").indexOf("application/x-www-form-urlencoded")&&Ut.test(e.data)&&"data");if(a||"jsonp"===e.dataTypes[0])return r=e.jsonpCallback=m(e.jsonpCallback)?e.jsonpCallback():e.jsonpCallback,a?e[a]=e[a].replace(Ut,"$1"+r):!1!==e.jsonp&&(e.url+=(Tt.test(e.url)?"&":"?")+e.jsonp+"="+r),e.converters["script json"]=function(){return o||S.error(r+" was not called"),o[0]},e.dataTypes[0]="json",i=C[r],C[r]=function(){o=arguments},n.always(function(){void 0===i?S(C).removeProp(r):C[r]=i,e[r]&&(e.jsonpCallback=t.jsonpCallback,zt.push(r)),o&&m(i)&&i(o[0]),o=i=void 0}),"script"}),y.createHTMLDocument=((_t=E.implementation.createHTMLDocument("").body).innerHTML="
",2===_t.childNodes.length),S.parseHTML=function(e,t,n){return"string"!=typeof e?[]:("boolean"==typeof t&&(n=t,t=!1),t||(y.createHTMLDocument?((r=(t=E.implementation.createHTMLDocument("")).createElement("base")).href=E.location.href,t.head.appendChild(r)):t=E),o=!n&&[],(i=N.exec(e))?[t.createElement(i[1])]:(i=xe([e],t,o),o&&o.length&&S(o).remove(),S.merge([],i.childNodes)));var r,i,o},S.fn.load=function(e,t,n){var r,i,o,a=this,s=e.indexOf(" ");return-1").append(S.parseHTML(e)).find(r):e)}).always(n&&function(e,t){a.each(function(){n.apply(this,o||[e.responseText,t,e])})}),this},S.expr.pseudos.animated=function(t){return S.grep(S.timers,function(e){return t===e.elem}).length},S.offset={setOffset:function(e,t,n){var r,i,o,a,s,u,l=S.css(e,"position"),c=S(e),f={};"static"===l&&(e.style.position="relative"),s=c.offset(),o=S.css(e,"top"),u=S.css(e,"left"),("absolute"===l||"fixed"===l)&&-1<(o+u).indexOf("auto")?(a=(r=c.position()).top,i=r.left):(a=parseFloat(o)||0,i=parseFloat(u)||0),m(t)&&(t=t.call(e,n,S.extend({},s))),null!=t.top&&(f.top=t.top-s.top+a),null!=t.left&&(f.left=t.left-s.left+i),"using"in t?t.using.call(e,f):c.css(f)}},S.fn.extend({offset:function(t){if(arguments.length)return void 0===t?this:this.each(function(e){S.offset.setOffset(this,t,e)});var e,n,r=this[0];return r?r.getClientRects().length?(e=r.getBoundingClientRect(),n=r.ownerDocument.defaultView,{top:e.top+n.pageYOffset,left:e.left+n.pageXOffset}):{top:0,left:0}:void 0},position:function(){if(this[0]){var e,t,n,r=this[0],i={top:0,left:0};if("fixed"===S.css(r,"position"))t=r.getBoundingClientRect();else{t=this.offset(),n=r.ownerDocument,e=r.offsetParent||n.documentElement;while(e&&(e===n.body||e===n.documentElement)&&"static"===S.css(e,"position"))e=e.parentNode;e&&e!==r&&1===e.nodeType&&((i=S(e).offset()).top+=S.css(e,"borderTopWidth",!0),i.left+=S.css(e,"borderLeftWidth",!0))}return{top:t.top-i.top-S.css(r,"marginTop",!0),left:t.left-i.left-S.css(r,"marginLeft",!0)}}},offsetParent:function(){return this.map(function(){var e=this.offsetParent;while(e&&"static"===S.css(e,"position"))e=e.offsetParent;return e||re})}}),S.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(t,i){var o="pageYOffset"===i;S.fn[t]=function(e){return $(this,function(e,t,n){var r;if(x(e)?r=e:9===e.nodeType&&(r=e.defaultView),void 0===n)return r?r[i]:e[t];r?r.scrollTo(o?r.pageXOffset:n,o?n:r.pageYOffset):e[t]=n},t,e,arguments.length)}}),S.each(["top","left"],function(e,n){S.cssHooks[n]=Fe(y.pixelPosition,function(e,t){if(t)return t=We(e,n),Pe.test(t)?S(e).position()[n]+"px":t})}),S.each({Height:"height",Width:"width"},function(a,s){S.each({padding:"inner"+a,content:s,"":"outer"+a},function(r,o){S.fn[o]=function(e,t){var n=arguments.length&&(r||"boolean"!=typeof e),i=r||(!0===e||!0===t?"margin":"border");return $(this,function(e,t,n){var r;return x(e)?0===o.indexOf("outer")?e["inner"+a]:e.document.documentElement["client"+a]:9===e.nodeType?(r=e.documentElement,Math.max(e.body["scroll"+a],r["scroll"+a],e.body["offset"+a],r["offset"+a],r["client"+a])):void 0===n?S.css(e,t,i):S.style(e,t,n,i)},s,n?e:void 0,n)}})}),S.each(["ajaxStart","ajaxStop","ajaxComplete","ajaxError","ajaxSuccess","ajaxSend"],function(e,t){S.fn[t]=function(e){return this.on(t,e)}}),S.fn.extend({bind:function(e,t,n){return this.on(e,null,t,n)},unbind:function(e,t){return this.off(e,null,t)},delegate:function(e,t,n,r){return this.on(t,e,n,r)},undelegate:function(e,t,n){return 1===arguments.length?this.off(e,"**"):this.off(t,e||"**",n)},hover:function(e,t){return this.mouseenter(e).mouseleave(t||e)}}),S.each("blur focus focusin focusout resize scroll click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup contextmenu".split(" "),function(e,n){S.fn[n]=function(e,t){return 0TypeElement or a TypeParameterElement. - * @param method target - * @return a type + /* + * Returns the closest superclass (not the superinterface) that contains + * a method that is both: + * + * - overridden by the specified method, and + * - is not itself a *simple* override + * + * If no such class can be found, returns null. + * + * If the specified method belongs to an interface, the only considered + * superclass is java.lang.Object no matter how many other interfaces + * that interface extends. */ - public TypeMirror overriddenType(ExecutableElement method) { + public DeclaredType overriddenType(ExecutableElement method) { if (utils.isStatic(method)) { return null; } MethodSymbol sym = (MethodSymbol) method; ClassSymbol origin = (ClassSymbol) sym.owner; - for (com.sun.tools.javac.code.Type t = javacTypes.supertype(origin.type); - t.hasTag(TypeTag.CLASS); - t = javacTypes.supertype(t)) { + for (Type t = javacTypes.supertype(origin.type); + t.hasTag(TypeTag.CLASS); + t = javacTypes.supertype(t)) { ClassSymbol c = (ClassSymbol) t.tsym; - for (com.sun.tools.javac.code.Symbol sym2 : c.members().getSymbolsByName(sym.name)) { + for (Symbol sym2 : c.members().getSymbolsByName(sym.name)) { if (sym.overrides(sym2, origin, javacTypes, true)) { // Ignore those methods that may be a simple override // and allow the real API method to be found. - if (sym2.type.hasTag(TypeTag.METHOD) && - utils.isSimpleOverride((MethodSymbol)sym2)) { + if (utils.isSimpleOverride((MethodSymbol)sym2)) { continue; } - return t; + assert t.hasTag(TypeTag.CLASS) && !t.isInterface(); + return (Type.ClassType) t; } } } diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/ClassBuilder.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/ClassBuilder.java index 5642ebaad75efc24acf0ef1b58cb772ece594571..0d3e881adac330932ea3ab507ae8ce65801322f6 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/ClassBuilder.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/ClassBuilder.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 @@ -108,12 +108,12 @@ public class ClassBuilder extends AbstractBuilder { buildClassDoc(); } - /** - * Handles the {@literal } tag. - * - * @throws DocletException if there is a problem while building the documentation - */ - protected void buildClassDoc() throws DocletException { + /** + * Handles the {@literal } tag. + * + * @throws DocletException if there is a problem while building the documentation + */ + protected void buildClassDoc() throws DocletException { String key = switch (typeElement.getKind()) { case INTERFACE -> "doclet.Interface"; case ENUM -> "doclet.Enum"; @@ -122,7 +122,7 @@ public class ClassBuilder extends AbstractBuilder { case CLASS -> "doclet.Class"; default -> throw new IllegalStateException(typeElement.getKind() + " " + typeElement); }; - Content contentTree = writer.getHeader(resources.getText(key) + " " + Content contentTree = writer.getHeader(resources.getText(key) + " " + utils.getSimpleName(typeElement)); Content classContentTree = writer.getClassContentHeader(); @@ -137,11 +137,11 @@ public class ClassBuilder extends AbstractBuilder { copyDocFiles(); } - /** - * Build the class tree documentation. - * - * @param classContentTree the content tree to which the documentation will be added - */ + /** + * Build the class tree documentation. + * + * @param classContentTree the content tree to which the documentation will be added + */ protected void buildClassTree(Content classContentTree) { writer.addClassTree(classContentTree); } @@ -256,7 +256,7 @@ public class ClassBuilder extends AbstractBuilder { * * @throws DocFileIOException if there is a problem while copying the files */ - private void copyDocFiles() throws DocletException { + private void copyDocFiles() throws DocletException { PackageElement containingPackage = utils.containingPackage(typeElement); if ((configuration.packages == null || !configuration.packages.contains(containingPackage)) && @@ -270,7 +270,7 @@ public class ClassBuilder extends AbstractBuilder { docFilesHandler.copyDocFiles(); containingPackagesSeen.add(containingPackage); } - } + } /** * Build the signature of the current class. @@ -287,7 +287,7 @@ public class ClassBuilder extends AbstractBuilder { * @param classInfoTree the content tree to which the documentation will be added */ protected void buildClassDescription(Content classInfoTree) { - writer.addClassDescription(classInfoTree); + writer.addClassDescription(classInfoTree); } /** @@ -296,7 +296,7 @@ public class ClassBuilder extends AbstractBuilder { * @param classInfoTree the content tree to which the documentation will be added */ protected void buildClassTagInfo(Content classInfoTree) { - writer.addClassTagInfo(classInfoTree); + writer.addClassTagInfo(classInfoTree); } /** diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/taglets/ThrowsTaglet.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/taglets/ThrowsTaglet.java index 88a947ffdc719e0ca6497b36dcda2a97f19a41f0..9e3213e68a778efbd5db75c2ca1ddaa7cc991131 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/taglets/ThrowsTaglet.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/taglets/ThrowsTaglet.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,6 +42,7 @@ import javax.lang.model.element.ExecutableElement; import javax.lang.model.element.TypeElement; import javax.lang.model.type.ExecutableType; import javax.lang.model.type.TypeMirror; +import javax.lang.model.util.Types; import com.sun.source.doctree.DocTree; import com.sun.source.doctree.ThrowsTree; @@ -166,7 +167,9 @@ public class ThrowsTaglet extends BaseTaglet writer.getCurrentPageElement(), (ExecutableElement)holder); List thrownTypes = instantiatedType.getThrownTypes(); Map typeSubstitutions = getSubstitutedThrownTypes( - ((ExecutableElement) holder).getThrownTypes(), thrownTypes); + writer.configuration().utils.typeUtils, + ((ExecutableElement) holder).getThrownTypes(), + thrownTypes); Map, ExecutableElement> tagsMap = new LinkedHashMap<>(); tagsMap.put(utils.getThrowsTrees(execHolder), execHolder); Content result = writer.getOutputInstance(); @@ -233,7 +236,8 @@ public class ThrowsTaglet extends BaseTaglet * @param instantiatedThrownTypes the thrown types in the context of the current type. * @return map of declared to instantiated thrown types or an empty map. */ - private Map getSubstitutedThrownTypes(List declaredThrownTypes, + private Map getSubstitutedThrownTypes(Types types, + List declaredThrownTypes, List instantiatedThrownTypes) { if (!instantiatedThrownTypes.equals(declaredThrownTypes)) { Map map = new HashMap<>(); @@ -242,7 +246,7 @@ public class ThrowsTaglet extends BaseTaglet while (i1.hasNext() && i2.hasNext()) { TypeMirror t1 = i1.next(); TypeMirror t2 = i2.next(); - if (!t1.equals(t2)) + if (!types.isSameType(t1, t2)) map.put(t2.toString(), t1); } return map; diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/DocPaths.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/DocPaths.java index b96ada5367b9d0d2d6974cfa8729bc9397162022..b8c90fee82309b334cc7b6d9ca6f10820d158392 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/DocPaths.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/DocPaths.java @@ -104,7 +104,7 @@ public class DocPaths { public static final DocPath JQUERY_OVERRIDES_CSS = DocPath.create("jquery-ui.overrides.css"); /** The name of the default jQuery javascript file. */ - public static final DocPath JQUERY_JS = DocPath.create("jquery-3.5.1.min.js"); + public static final DocPath JQUERY_JS = DocPath.create("jquery-3.6.0.min.js"); /** The name of the default jQuery UI stylesheet file. */ public static final DocPath JQUERY_UI_CSS = DocPath.create("jquery-ui.min.css"); diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/UncheckedDocletException.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/UncheckedDocletException.java index b1644b439ca5870733923a74a198a066d54d66a4..5c358b784023f93816f28aea07eccaf0f54c7b00 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/UncheckedDocletException.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/UncheckedDocletException.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 @@ -45,12 +45,7 @@ public class UncheckedDocletException extends Error { } @Override - public synchronized Throwable getCause() { - return super.getCause(); - } - - @Override - public synchronized Throwable initCause(Throwable cause) { + public Throwable initCause(Throwable cause) { throw new UnsupportedOperationException(); } } diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/Utils.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/Utils.java index ec7b14c5b4f6385becd3a07d986f595e363fe459..21f16a01c5c1bdc87dc2c8b61f7dfe37a6c2e696 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/Utils.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/Utils.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2021, 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 @@ -159,27 +159,22 @@ public class Utils { } // our own little symbol table - private HashMap symtab = new HashMap<>(); + private final Map symtab = new HashMap<>(); public TypeMirror getSymbol(String signature) { - TypeMirror type = symtab.get(signature); - if (type == null) { - TypeElement typeElement = elementUtils.getTypeElement(signature); - if (typeElement == null) - return null; - type = typeElement.asType(); - if (type == null) - return null; - symtab.put(signature, type); - } - return type; + return symtab.computeIfAbsent(signature, s -> { + var typeElement = elementUtils.getTypeElement(s); + return typeElement == null ? null : typeElement.asType(); + }); } public TypeMirror getObjectType() { return getSymbol("java.lang.Object"); } - public TypeMirror getThrowableType() { return getSymbol("java.lang.Throwable"); } + public TypeMirror getThrowableType() { + return getSymbol("java.lang.Throwable"); + } public TypeMirror getSerializableType() { return getSymbol("java.io.Serializable"); @@ -189,14 +184,6 @@ public class Utils { return getSymbol("java.io.Externalizable"); } - public TypeMirror getIllegalArgumentExceptionType() { - return getSymbol("java.lang.IllegalArgumentException"); - } - - public TypeMirror getNullPointerExceptionType() { - return getSymbol("java.lang.NullPointerException"); - } - public TypeMirror getDeprecatedType() { return getSymbol("java.lang.Deprecated"); } @@ -205,22 +192,6 @@ public class Utils { return getSymbol("java.lang.FunctionalInterface"); } - /** - * Return array of class members whose documentation is to be generated. - * If the member is deprecated do not include such a member in the - * returned array. - * - * @param members Array of members to choose from. - * @return List List of eligible members for whom - * documentation is getting generated. - */ - public List excludeDeprecatedMembers(List members) { - return members.stream() - .filter(member -> !isDeprecated(member)) - .sorted(comparators.makeGeneralPurposeComparator()) - .collect(Collectors.toCollection(ArrayList::new)); - } - /** * Search for the given method in the given class. * @@ -241,9 +212,9 @@ public class Utils { /** * Test whether a class is a subclass of another class. * - * @param t1 the candidate superclass. - * @param t2 the target - * @return true if t1 is a superclass of t2. + * @param t1 the candidate subclass + * @param t2 the candidate superclass + * @return true if t1 is a superclass of t2 */ public boolean isSubclassOf(TypeElement t1, TypeElement t2) { return typeUtils.isSubtype(typeUtils.erasure(t1.asType()), typeUtils.erasure(t2.asType())); @@ -261,20 +232,14 @@ public class Utils { List parameters2 = e2.getParameters(); if (e1.getSimpleName().equals(e2.getSimpleName()) && parameters1.size() == parameters2.size()) { - int j; - for (j = 0 ; j < parameters1.size(); j++) { + for (int j = 0; j < parameters1.size(); j++) { VariableElement v1 = parameters1.get(j); VariableElement v2 = parameters2.get(j); - String t1 = getTypeName(v1.asType(), true); - String t2 = getTypeName(v2.asType(), true); - if (!(t1.equals(t2) || - isTypeVariable(v1.asType()) || isTypeVariable(v2.asType()))) { - break; + if (!typeUtils.isSameType(v1.asType(), v2.asType())) { + return false; } } - if (j == parameters1.size()) { - return true; - } + return true; } return false; } else { @@ -320,10 +285,6 @@ public class Utils { return !e.getAnnotationMirrors().isEmpty(); } - public boolean isAnnotated(Element e) { - return !e.getAnnotationMirrors().isEmpty(); - } - public boolean isAnnotationType(Element e) { return new SimpleElementVisitor14() { @Override @@ -361,10 +322,6 @@ public class Utils { return e.getKind() == ENUM; } - boolean isEnumConstant(Element e) { - return e.getKind() == ENUM_CONSTANT; - } - public boolean isField(Element e) { return e.getKind() == FIELD; } @@ -511,57 +468,26 @@ public class Utils { return typeUtils.isSubtype(te.asType(), getThrowableType()); } - public boolean isPrimitive(TypeMirror t) { - return new SimpleTypeVisitor14() { - - @Override - public Boolean visitNoType(NoType t, Void p) { - return t.getKind() == VOID; - } - @Override - public Boolean visitPrimitive(PrimitiveType t, Void p) { - return true; - } - @Override - public Boolean visitArray(ArrayType t, Void p) { - return visit(t.getComponentType()); - } - @Override - protected Boolean defaultAction(TypeMirror e, Void p) { - return false; - } - }.visit(t); - } - public boolean isExecutableElement(Element e) { - ElementKind kind = e.getKind(); - switch (kind) { - case CONSTRUCTOR: case METHOD: case INSTANCE_INIT: - return true; - default: - return false; - } + return switch (e.getKind()) { + case CONSTRUCTOR, METHOD, INSTANCE_INIT -> true; + default -> false; + }; } public boolean isVariableElement(Element e) { - ElementKind kind = e.getKind(); - switch(kind) { - case ENUM_CONSTANT: case EXCEPTION_PARAMETER: case FIELD: - case LOCAL_VARIABLE: case PARAMETER: - case RESOURCE_VARIABLE: - return true; - default: - return false; - } + return switch (e.getKind()) { + case ENUM_CONSTANT, EXCEPTION_PARAMETER, FIELD, LOCAL_VARIABLE, + PARAMETER, RESOURCE_VARIABLE -> true; + default -> false; + }; } public boolean isTypeElement(Element e) { - switch (e.getKind()) { - case CLASS: case ENUM: case INTERFACE: case ANNOTATION_TYPE: case RECORD: - return true; - default: - return false; - } + return switch (e.getKind()) { + case CLASS, ENUM, INTERFACE, ANNOTATION_TYPE, RECORD -> true; + default -> false; + }; } /** @@ -693,14 +619,6 @@ public class Utils { return t.getKind() == DECLARED; } - public boolean isErrorType(TypeMirror t) { - return t.getKind() == ERROR; - } - - public boolean isIntersectionType(TypeMirror t) { - return t.getKind() == INTERSECTION; - } - public boolean isTypeParameterElement(Element e) { return e.getKind() == TYPE_PARAMETER; } @@ -713,12 +631,8 @@ public class Utils { return t.getKind() == VOID; } - public boolean isWildCard(TypeMirror t) { - return t.getKind() == WILDCARD; - } - public boolean ignoreBounds(TypeMirror bound) { - return bound.equals(getObjectType()) && !isAnnotated(bound); + return typeUtils.isSameType(bound, getObjectType()) && !isAnnotated(bound); } /* @@ -783,11 +697,20 @@ public class Utils { !((DeclaredType)e.getEnclosingElement().asType()).getTypeArguments().isEmpty(); } - /** - * Return the type containing the method that this method overrides. - * It may be a {@code TypeElement} or a {@code TypeParameterElement}. + /* + * Returns the closest superclass (not the superinterface) that contains + * a method that is both: + * + * - overridden by the specified method, and + * - is not itself a *simple* override + * + * If no such class can be found, returns null. + * + * If the specified method belongs to an interface, the only considered + * superclass is java.lang.Object no matter how many other interfaces + * that interface extends. */ - public TypeMirror overriddenType(ExecutableElement method) { + public DeclaredType overriddenType(ExecutableElement method) { return configuration.workArounds.overriddenType(method); } @@ -800,28 +723,14 @@ public class Utils { return getType(t); } - /** - * Return the class that originally defined the method that - * is overridden by the current definition, or null if no - * such class exists. - * - * @return a TypeElement representing the superclass that - * originally defined this method, null if this method does - * not override a definition in a superclass. - */ - public TypeElement overriddenClass(ExecutableElement ee) { - TypeMirror type = overriddenType(ee); - return (type != null) ? asTypeElement(type) : null; - } - public ExecutableElement overriddenMethod(ExecutableElement method) { if (isStatic(method)) { return null; } final TypeElement origin = getEnclosingTypeElement(method); for (TypeMirror t = getSuperType(origin); - t.getKind() == DECLARED; - t = getSuperType(asTypeElement(t))) { + t.getKind() == DECLARED; + t = getSuperType(asTypeElement(t))) { TypeElement te = asTypeElement(t); if (te == null) { return null; @@ -834,7 +743,7 @@ public class Utils { return ee; } } - if (t.equals(getObjectType())) + if (typeUtils.isSameType(t, getObjectType())) return null; } return null; @@ -916,30 +825,69 @@ public class Utils { */ public Set getAllInterfaces(TypeElement te) { Set results = new LinkedHashSet<>(); - getAllInterfaces(te.asType(), results); + addSuperInterfaces(te.asType(), results, new HashSet<>()); + assert noSameTypes(results); return results; } - private void getAllInterfaces(TypeMirror type, Set results) { - List intfacs = typeUtils.directSupertypes(type); + private boolean noSameTypes(Set results) { + for (TypeMirror t1 : results) { + for (TypeMirror t2 : results) { + if (t1 == t2) { + continue; + } + if (typeUtils.isSameType(t1, t2)) { + return false; + } + } + } + return true; + } + + /* + * Instances of TypeMirror should be compared using + * Types.isSameType. However, there's no hash function + * consistent with that method. This makes it problematic to + * store TypeMirror in a collection that relies on hashing. + * + * To work around that, along with accumulating the resulting set of type + * mirrors, we also maintain a set of elements that correspond to those + * type mirrors. Element provides strong equals and hashCode. We only add + * a type mirror into the result set if we don't already have an element + * that corresponds to this type mirror in the set of seen elements. + * + * Although this might seem wrong, as an instance of Element corresponds + * to multiple instances of TypeMirror (one-to-many), in an + * inheritance hierarchy the correspondence is effectively one-to-one. + * This is because it is NOT possible for a type to be a subtype + * of different generic invocations of the same supertype; e.g., + * + * interface X extends G, G + */ + private void addSuperInterfaces(TypeMirror type, Set results, Set visited) { TypeMirror superType = null; - for (TypeMirror intfac : intfacs) { - if (intfac == getObjectType()) + for (TypeMirror t : typeUtils.directSupertypes(type)) { + if (typeUtils.isSameType(t, getObjectType())) continue; - TypeElement e = asTypeElement(intfac); + TypeElement e = asTypeElement(t); if (isInterface(e)) { - if (isPublic(e) || isLinkable(e)) - results.add(intfac); - - getAllInterfaces(intfac, results); + if (!visited.add(e)) { + continue; // seen it before + } + if (isPublic(e) || isLinkable(e)) { + results.add(t); + } + addSuperInterfaces(t, results, visited); } else { + // there can be at most one superclass and it is not null + assert superType == null && t != null : superType; // Save the supertype for later. - superType = intfac; + superType = t; } } // Collect the super-interfaces of the supertype. if (superType != null) - getAllInterfaces(superType, results); + addSuperInterfaces(superType, results, visited); } /** @@ -995,13 +943,6 @@ public class Utils { return searchResult; } - /** - * Enclose in quotes, used for paths and filenames that contains spaces - */ - public String quote(String filepath) { - return ("\"" + filepath + "\""); - } - /** * Parse the package name. We only want to display package name up to * 2 levels. @@ -1176,8 +1117,7 @@ public class Utils { } public TypeElement getSuperClass(TypeElement te) { - if (isInterface(te) || isAnnotationType(te) || - te.asType().equals(getObjectType())) { + if (checkType(te)) { return null; } TypeMirror superclass = te.getSuperclass(); @@ -1187,9 +1127,13 @@ public class Utils { return asTypeElement(superclass); } + private boolean checkType(TypeElement te) { + return isInterface(te) || typeUtils.isSameType(te.asType(), getObjectType()) + || isAnnotationType(te); + } + public TypeElement getFirstVisibleSuperClassAsTypeElement(TypeElement te) { - if (isAnnotationType(te) || isInterface(te) || - te.asType().equals(getObjectType())) { + if (checkType(te)) { return null; } TypeMirror firstVisibleSuperClass = getFirstVisibleSuperClass(te); @@ -1202,7 +1146,6 @@ public class Utils { * @return the closest visible super class. Return null if it cannot * be found. */ - public TypeMirror getFirstVisibleSuperClass(TypeMirror type) { return getFirstVisibleSuperClass(asTypeElement(type)); } @@ -1213,7 +1156,7 @@ public class Utils { * * @param te the TypeElement to be interrogated * @return the closest visible super class. Return null if it cannot - * be found.. + * be found. */ public TypeMirror getFirstVisibleSuperClass(TypeElement te) { TypeMirror superType = te.getSuperclass(); @@ -1233,7 +1176,7 @@ public class Utils { superType = supersuperType; superClass = supersuperClass; } - if (te.asType().equals(superType)) { + if (typeUtils.isSameType(te.asType(), superType)) { return null; } return superType; @@ -1481,10 +1424,14 @@ public class Utils { return hasBlockTag(e, DocTree.Kind.HIDDEN); } - /** - * Returns true if the method has no comments, or a lone @inheritDoc. - * @param m a method - * @return true if there are no comments, false otherwise + /* + * Returns true if the passed method does not change the specification it + * inherited. + * + * If the passed method is not deprecated and has either no comment or a + * comment consisting of single {@inheritDoc} tag, the inherited + * specification is deemed unchanged and this method returns true; + * otherwise this method returns false. */ public boolean isSimpleOverride(ExecutableElement m) { if (!options.summarizeOverriddenMethods() || !isIncluded(m)) { @@ -1562,19 +1509,6 @@ public class Utils { return compareStrings(true, s1, s2); } - /** - * A general purpose case sensitive String comparator, which - * compares two Strings using a Collator strength of "SECONDARY". - * - * @param s1 first String to compare. - * @param s2 second String to compare. - * @return a negative integer, zero, or a positive integer as the first - * argument is less than, equal to, or greater than the second. - */ - public int compareCaseCompare(String s1, String s2) { - return compareStrings(false, s1, s2); - } - private DocCollator tertiaryCollator = null; private DocCollator secondaryCollator = null; @@ -1766,26 +1700,6 @@ public class Utils { } - /** - * Returns the documented annotation interfaces in a package. - * - * @param pkg the package - * @return the annotation interfaces - */ - public List getAnnotationTypes(PackageElement pkg) { - return getDocumentedItems(pkg, ANNOTATION_TYPE, TypeElement.class); - } - - /** - * Returns the documented record classes in a package. - * - * @param pkg the package - * @return the record classes - */ - public List getRecords(PackageElement pkg) { - return getDocumentedItems(pkg, RECORD, TypeElement.class); - } - /** * Returns the documented fields in a type element. * @@ -1838,13 +1752,6 @@ public class Utils { return getDocumentedItems(te, METHOD, ExecutableElement.class); } - public int getOrdinalValue(VariableElement member) { - if (member == null || member.getKind() != ENUM_CONSTANT) { - throw new IllegalArgumentException("must be an enum constant: " + member); - } - return member.getEnclosingElement().getEnclosedElements().indexOf(member); - } - private Map> modulePackageMap = null; public Map> getModulePackageMap() { if (modulePackageMap == null) { @@ -1916,16 +1823,6 @@ public class Utils { return lineMap.getLineNumber(pos); } - /** - * Returns the documented interfaces in a package. - * - * @param pkg the package - * @return the interfaces - */ - public List getInterfaces(PackageElement pkg) { - return getDocumentedItems(pkg, INTERFACE, TypeElement.class); - } - /** * Returns the documented enum constants in a type element. * @@ -1936,16 +1833,6 @@ public class Utils { return getDocumentedItems(te, ENUM_CONSTANT, VariableElement.class); } - /** - * Returns the documented enum classes in a package. - * - * @param pkg the package - * @return the interfaces - */ - public List getEnums(PackageElement pkg) { - return getDocumentedItems(pkg, ENUM, TypeElement.class); - } - /** * Returns all the classes in a package. * @@ -2347,102 +2234,6 @@ public class Utils { return mdle.getQualifiedName().toString(); } - public boolean isAttribute(DocTree doctree) { - return isKind(doctree, ATTRIBUTE); - } - - public boolean isAuthor(DocTree doctree) { - return isKind(doctree, AUTHOR); - } - - public boolean isComment(DocTree doctree) { - return isKind(doctree, COMMENT); - } - - public boolean isDeprecated(DocTree doctree) { - return isKind(doctree, DEPRECATED); - } - - public boolean isDocComment(DocTree doctree) { - return isKind(doctree, DOC_COMMENT); - } - - public boolean isDocRoot(DocTree doctree) { - return isKind(doctree, DOC_ROOT); - } - - public boolean isEndElement(DocTree doctree) { - return isKind(doctree, END_ELEMENT); - } - - public boolean isEntity(DocTree doctree) { - return isKind(doctree, ENTITY); - } - - public boolean isErroneous(DocTree doctree) { - return isKind(doctree, ERRONEOUS); - } - - public boolean isException(DocTree doctree) { - return isKind(doctree, EXCEPTION); - } - - public boolean isIdentifier(DocTree doctree) { - return isKind(doctree, IDENTIFIER); - } - - public boolean isInheritDoc(DocTree doctree) { - return isKind(doctree, INHERIT_DOC); - } - - public boolean isLink(DocTree doctree) { - return isKind(doctree, LINK); - } - - public boolean isLinkPlain(DocTree doctree) { - return isKind(doctree, LINK_PLAIN); - } - - public boolean isLiteral(DocTree doctree) { - return isKind(doctree, LITERAL); - } - - public boolean isOther(DocTree doctree) { - return doctree.getKind() == DocTree.Kind.OTHER; - } - - public boolean isParam(DocTree doctree) { - return isKind(doctree, PARAM); - } - - public boolean isReference(DocTree doctree) { - return isKind(doctree, REFERENCE); - } - - public boolean isReturn(DocTree doctree) { - return isKind(doctree, RETURN); - } - - public boolean isSee(DocTree doctree) { - return isKind(doctree, SEE); - } - - public boolean isSerial(DocTree doctree) { - return isKind(doctree, SERIAL); - } - - public boolean isSerialData(DocTree doctree) { - return isKind(doctree, SERIAL_DATA); - } - - public boolean isSerialField(DocTree doctree) { - return isKind(doctree, SERIAL_FIELD); - } - - public boolean isSince(DocTree doctree) { - return isKind(doctree, SINCE); - } - public boolean isStartElement(DocTree doctree) { return isKind(doctree, START_ELEMENT); } @@ -2451,26 +2242,6 @@ public class Utils { return isKind(doctree, TEXT); } - public boolean isThrows(DocTree doctree) { - return isKind(doctree, THROWS); - } - - public boolean isUnknownBlockTag(DocTree doctree) { - return isKind(doctree, UNKNOWN_BLOCK_TAG); - } - - public boolean isUnknownInlineTag(DocTree doctree) { - return isKind(doctree, UNKNOWN_INLINE_TAG); - } - - public boolean isValue(DocTree doctree) { - return isKind(doctree, VALUE); - } - - public boolean isVersion(DocTree doctree) { - return isKind(doctree, VERSION); - } - private boolean isKind(DocTree doctree, DocTree.Kind match) { return doctree.getKind() == match; } @@ -2516,10 +2287,6 @@ public class Utils { return getBlockTags(element, t -> t.getKind() == kind, tClass); } - public List getBlockTags(Element element, DocTree.Kind kind, DocTree.Kind altKind) { - return getBlockTags(element, t -> t.getKind() == kind || t.getKind() == altKind); - } - public List getBlockTags(Element element, Taglet taglet) { return getBlockTags(element, t -> { if (taglet instanceof BaseTaglet baseTaglet) { @@ -2592,7 +2359,7 @@ public class Utils { /** * A cache of doc comment info objects for elements. - * The entries may come from the AST and DocCommentParser, or may be autromatically + * The entries may come from the AST and DocCommentParser, or may be automatically * generated comments for mandated elements and JavaFX properties. * * @see CommentUtils#dcInfoMap @@ -2795,19 +2562,6 @@ public class Utils { return elementUtils.getPackageOf(e); } - public TypeElement getTopMostContainingTypeElement(Element e) { - if (isPackage(e)) { - return null; - } - TypeElement outer = getEnclosingTypeElement(e); - if (outer == null) - return (TypeElement)e; - while (outer != null && outer.getNestingKind().isNested()) { - outer = getEnclosingTypeElement(outer); - } - return outer; - } - /** * A memory-sensitive cache for {@link CommentHelper} objects, * which are expensive to compute. @@ -3053,9 +2807,11 @@ public class Utils { */ public boolean isPreviewAPI(Element el) { boolean parentPreviewAPI = false; - Element enclosing = el.getEnclosingElement(); - if (enclosing != null && (enclosing.getKind().isClass() || enclosing.getKind().isInterface())) { - parentPreviewAPI = configuration.workArounds.isPreviewAPI(enclosing); + if (!isClassOrInterface(el)) { + Element enclosing = el.getEnclosingElement(); + if (isClassOrInterface(enclosing)) { + parentPreviewAPI = configuration.workArounds.isPreviewAPI(enclosing); + } } boolean previewAPI = configuration.workArounds.isPreviewAPI(el); return !parentPreviewAPI && previewAPI; @@ -3082,18 +2838,12 @@ public class Utils { */ public Set elementFlags(Element el) { Set flags = EnumSet.noneOf(ElementFlag.class); - PreviewSummary previewAPIs = declaredUsingPreviewAPIs(el); if (isDeprecated(el)) { flags.add(ElementFlag.DEPRECATED); } - if ((!previewLanguageFeaturesUsed(el).isEmpty() || - configuration.workArounds.isPreviewAPI(el) || - !previewAPIs.previewAPI.isEmpty() || - !previewAPIs.reflectivePreviewAPI.isEmpty() || - !previewAPIs.declaredUsingPreviewFeature.isEmpty()) && - !hasNoProviewAnnotation(el)) { + if (previewFlagProvider.isPreview(el)) { flags.add(ElementFlag.PREVIEW); } @@ -3109,9 +2859,42 @@ public class Utils { PREVIEW } - private boolean hasNoProviewAnnotation(Element el) { + private boolean isClassOrInterface(Element el) { + return el != null && (el.getKind().isClass() || el.getKind().isInterface()); + } + + private boolean hasNoPreviewAnnotation(Element el) { return el.getAnnotationMirrors() .stream() .anyMatch(am -> "jdk.internal.javac.NoPreview".equals(getQualifiedTypeName(am.getAnnotationType()))); } + + private PreviewFlagProvider previewFlagProvider = new PreviewFlagProvider() { + @Override + public boolean isPreview(Element el) { + PreviewSummary previewAPIs = declaredUsingPreviewAPIs(el); + Element enclosing = el.getEnclosingElement(); + + return ( !previewLanguageFeaturesUsed(el).isEmpty() + || configuration.workArounds.isPreviewAPI(el) + || ( !isClassOrInterface(el) && isClassOrInterface(enclosing) + && configuration.workArounds.isPreviewAPI(enclosing)) + || !previewAPIs.previewAPI.isEmpty() + || !previewAPIs.reflectivePreviewAPI.isEmpty() + || !previewAPIs.declaredUsingPreviewFeature.isEmpty()) + && !hasNoPreviewAnnotation(el); + } + }; + + public PreviewFlagProvider setPreviewFlagProvider(PreviewFlagProvider provider) { + Objects.requireNonNull(provider); + PreviewFlagProvider old = previewFlagProvider; + previewFlagProvider = provider; + return old; + } + + public interface PreviewFlagProvider { + public boolean isPreview(Element el); + } + } diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/VisibleMemberTable.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/VisibleMemberTable.java index 096b23a2e1272a93e7839b8454dad172c441ed1d..5ef16d61fcf7642dc8d8a18bd9ba9f2ff3a2beae 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/VisibleMemberTable.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/VisibleMemberTable.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 @@ -43,6 +43,7 @@ import javax.lang.model.util.SimpleElementVisitor14; import javax.lang.model.util.SimpleTypeVisitor14; import java.lang.ref.SoftReference; import java.util.ArrayList; +import java.util.Collection; import java.util.Collections; import java.util.EnumMap; import java.util.EnumSet; @@ -63,12 +64,12 @@ import jdk.javadoc.internal.doclets.toolkit.PropertyUtils; /** * This class computes the main data structure for the doclet's * operations. Essentially, the implementation encapsulating the - * javax.lang.models view of what can be documented about a + * javax.lang.model's view of what can be documented about a * type element's members. *

* The general operations are as follows: *

- * Members: these are the members from jx.l.m's view but + * Members: these are the members from j.l.m's view but * are structured along the kinds of this class. *

* Extra Members: these are members enclosed in an undocumented @@ -146,23 +147,23 @@ public class VisibleMemberTable { } } - final TypeElement te; - final TypeElement parent; + private final TypeElement te; + private final TypeElement parent; - final BaseConfiguration config; - final BaseOptions options; - final Utils utils; - final VisibleMemberCache mcache; + private final BaseConfiguration config; + private final BaseOptions options; + private final Utils utils; + private final VisibleMemberCache mcache; private final List allSuperclasses; private final List allSuperinterfaces; private final List parents; - private Map> visibleMembers = null; + private Map> visibleMembers; private final Map propertyMap = new HashMap<>(); // Keeps track of method overrides - Map overriddenMethodTable + private final Map overriddenMethodTable = new LinkedHashMap<>(); protected VisibleMemberTable(TypeElement typeElement, BaseConfiguration configuration, @@ -178,7 +179,7 @@ public class VisibleMemberTable { parents = new ArrayList<>(); } - private synchronized void ensureInitialized() { + private void ensureInitialized() { if (visibleMembers != null) return; @@ -208,7 +209,7 @@ public class VisibleMemberTable { * a. The list may or may not contain simple overridden methods. * A simple overridden method is one that overrides a super method * with no specification changes as indicated by the existence of a - * sole @inheritDoc or devoid of any API comments. + * sole {@code @inheritDoc} or devoid of any API comments. *

* b.The list may contain (extra) members, inherited by inaccessible * super types, primarily package private types. These members are @@ -279,24 +280,22 @@ public class VisibleMemberTable { OverriddenMethodInfo found = overriddenMethodTable.get(e); if (found != null && (found.simpleOverride || utils.isUndocumentedEnclosure(utils.getEnclosingTypeElement(e)))) { - return found.overridden; + return found.overriddenMethod; } return null; } /** - * Returns the simply overridden method. + * {@return true if the specified method is NOT a simple override of some + * other method, otherwise false} + * * @param e the method to check - * @return the overridden method or null */ - public ExecutableElement getSimplyOverriddenMethod(ExecutableElement e) { + public boolean isNotSimpleOverride(ExecutableElement e) { ensureInitialized(); - OverriddenMethodInfo found = overriddenMethodTable.get(e); - if (found != null && found.simpleOverride) { - return found.overridden; - } - return null; + var info = overriddenMethodTable.get(e); + return info == null || !info.simpleOverride; } /** @@ -306,7 +305,7 @@ public class VisibleMemberTable { * order C, B, A, j.l.O. The super-interfaces however are * alpha sorted and appended to the resulting set. * - * @return the list of visible classes in this map. + * @return the set of visible classes in this map */ public Set getVisibleTypeElements() { ensureInitialized(); @@ -527,12 +526,11 @@ public class VisibleMemberTable { Map> overriddenByTable = new HashMap<>(); for (VisibleMemberTable pvmt : parents) { // Merge the lineage overrides into local table - pvmt.overriddenMethodTable.entrySet().forEach(e -> { - OverriddenMethodInfo p = e.getValue(); - if (!p.simpleOverride) { // consider only real overrides - List list = overriddenByTable.computeIfAbsent(p.overridden, + pvmt.overriddenMethodTable.forEach((method, methodInfo) -> { + if (!methodInfo.simpleOverride) { // consider only real overrides + List list = overriddenByTable.computeIfAbsent(methodInfo.overriddenMethod, k -> new ArrayList<>()); - list.add(e.getKey()); + list.add(method); } }); inheritedMethods.addAll(pvmt.getAllVisibleMembers(Kind.METHODS)); @@ -544,7 +542,7 @@ public class VisibleMemberTable { // c. are hidden in the type being considered // see allowInheritedMethod, which performs the above actions // nb. This statement has side effects that can initialize - // members of the overridenMethodTable field, so it must be + // members of the overriddenMethodTable field, so it must be // evaluated eagerly with toList(). List inheritedMethodsList = inheritedMethods.stream() .filter(e -> allowInheritedMethod((ExecutableElement) e, overriddenByTable, lmt)) @@ -565,7 +563,7 @@ public class VisibleMemberTable { // Merge the above list and stream, making sure the local methods precede the others // Final filtration of elements - List list = Stream.concat(localStream,inheritedMethodsList.stream()) + List list = Stream.concat(localStream, inheritedMethodsList.stream()) .filter(this::mustDocument) .toList(); @@ -575,7 +573,6 @@ public class VisibleMemberTable { for (VisibleMemberTable pvmt : parents) { overriddenMethodTable.putAll(pvmt.overriddenMethodTable); } - overriddenMethodTable = Collections.unmodifiableMap(overriddenMethodTable); } boolean isEnclosureInterface(Element e) { @@ -850,7 +847,7 @@ public class VisibleMemberTable { Map> map = memberMap.get(kind); return map.getOrDefault(key, Collections.emptyList()) .stream() - .map(e -> clazz.cast(e)) + .map(clazz::cast) .toList(); } @@ -967,7 +964,8 @@ public class VisibleMemberTable { // Future cleanups - Map> implementMethodsFinders = new HashMap<>(); + private final Map> + implementMethodsFinders = new HashMap<>(); private ImplementedMethods getImplementedMethodsFinder(ExecutableElement method) { SoftReference ref = implementMethodsFinders.get(method); @@ -983,7 +981,7 @@ public class VisibleMemberTable { public List getImplementedMethods(ExecutableElement method) { ImplementedMethods imf = getImplementedMethodsFinder(method); return imf.getImplementedMethods().stream() - .filter(m -> getSimplyOverriddenMethod(m) == null) + .filter(this::isNotSimpleOverride) .toList(); } @@ -996,112 +994,46 @@ public class VisibleMemberTable { private class ImplementedMethods { private final Map interfaces = new HashMap<>(); - private final List methlist = new ArrayList<>(); + private final LinkedHashSet methods = new LinkedHashSet<>(); public ImplementedMethods(ExecutableElement method) { - TypeElement typeElement = utils.getEnclosingTypeElement(method); + // ExecutableElement.getEnclosingElement() returns "the class or + // interface defining the executable", which has to be TypeElement + TypeElement typeElement = (TypeElement) method.getEnclosingElement(); Set intfacs = utils.getAllInterfaces(typeElement); - /* - * Search for the method in the list of interfaces. If found check if it is - * overridden by any other subinterface method which this class - * implements. If it is not overridden, add it in the method list. - * Do this recursively for all the extended interfaces for each interface - * from the list. - */ for (TypeMirror interfaceType : intfacs) { + // TODO: this method also finds static methods which are pseudo-inherited; + // this needs to be fixed ExecutableElement found = utils.findMethod(utils.asTypeElement(interfaceType), method); - if (found != null) { - removeOverriddenMethod(found); - if (!overridingMethodFound(found)) { - methlist.add(found); - interfaces.put(found, interfaceType); - } + if (found != null && !methods.contains(found)) { + methods.add(found); + interfaces.put(found, interfaceType); } } } /** - * Return the list of interface methods which the method passed in the + * Returns a collection of interface methods which the method passed in the * constructor is implementing. The search/build order is as follows: *

          * 1. Search in all the immediate interfaces which this method's class is
          *    implementing. Do it recursively for the superinterfaces as well.
          * 2. Traverse all the superclasses and search recursively in the
          *    interfaces which those superclasses implement.
-         *
+ * * - * @return SortedSet of implemented methods. + * @return a collection of implemented methods */ - List getImplementedMethods() { - return methlist; + Collection getImplementedMethods() { + return methods; } TypeMirror getMethodHolder(ExecutableElement ee) { return interfaces.get(ee); } - - /** - * Search in the method list and check if it contains a method which - * is overridden by the method as parameter. If found, remove the - * overridden method from the method list. - * - * @param method Is this method overriding a method in the method list. - */ - private void removeOverriddenMethod(ExecutableElement method) { - TypeElement overriddenClass = utils.overriddenClass(method); - if (overriddenClass != null) { - for (int i = 0; i < methlist.size(); i++) { - TypeElement te = utils.getEnclosingTypeElement(methlist.get(i)); - if (te == overriddenClass || utils.isSubclassOf(overriddenClass, te)) { - methlist.remove(i); // remove overridden method - return; - } - } - } - } - - /** - * Search in the already found methods' list and check if it contains - * a method which is overriding the method parameter or is the method - * parameter itself. - * - * @param method method to be searched - */ - private boolean overridingMethodFound(ExecutableElement method) { - TypeElement containingClass = utils.getEnclosingTypeElement(method); - for (ExecutableElement listmethod : methlist) { - if (containingClass == utils.getEnclosingTypeElement(listmethod)) { - // it's the same method. - return true; - } - TypeElement te = utils.overriddenClass(listmethod); - if (te == null) { - continue; - } - if (te == containingClass || utils.isSubclassOf(te, containingClass)) { - return true; - } - } - return false; - } } - /** - * A simple container to encapsulate an overridden method - * and the type of override. - */ - static class OverriddenMethodInfo { - final ExecutableElement overridden; - final boolean simpleOverride; - - public OverriddenMethodInfo(ExecutableElement overridden, boolean simpleOverride) { - this.overridden = overridden; - this.simpleOverride = simpleOverride; - } - - @Override - public String toString() { - return "OverriddenMethodInfo[" + overridden + ",simple:" + simpleOverride + "]"; - } + private record OverriddenMethodInfo(ExecutableElement overriddenMethod, + boolean simpleOverride) { } } diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/links/LinkFactory.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/links/LinkFactory.java index c5e6799022110bd95d29650c229c3beb81460254..04a238800cd07d7b43e595c4dbe57f1f22e4c1cf 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/links/LinkFactory.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/links/LinkFactory.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 @@ -151,7 +151,7 @@ public abstract class LinkFactory { // we get everything as extends java.lang.Object we suppress // all of them except those that have multiple extends if (bounds.size() == 1 && - bound.equals(utils.getObjectType()) && + utils.typeUtils.isSameType(bound, utils.getObjectType()) && !utils.isAnnotated(bound)) { continue; } diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclint/Checker.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclint/Checker.java index 446757513a17e6756089b1e5f04d5772a2fb7abd..6b167aa393329f1070d18dacaf118a6a74be9970 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclint/Checker.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclint/Checker.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 @@ -985,8 +985,8 @@ public class Checker extends DocTreePathScanner { } if (tree.isInline()) { DocCommentTree dct = getCurrentPath().getDocComment(); - if (tree != dct.getFirstSentence().get(0)) { - env.messages.warning(REFERENCE, tree, "dc.return.not.first"); + if (dct.getFirstSentence().isEmpty() || tree != dct.getFirstSentence().get(0)) { + env.messages.warning(SYNTAX, tree, "dc.return.not.first"); } } diff --git a/src/jdk.javadoc/share/legal/jquery.md b/src/jdk.javadoc/share/legal/jquery.md index 8054a34c8305c2a49f8eee5c34406521becdaa2b..f7b72e3fbeccff958a8e6eae219761d258043045 100644 --- a/src/jdk.javadoc/share/legal/jquery.md +++ b/src/jdk.javadoc/share/legal/jquery.md @@ -1,9 +1,9 @@ -## jQuery v3.5.1 +## jQuery v3.6.0 ### jQuery License ``` -jQuery v 3.5.1 -Copyright JS Foundation and other contributors, https://js.foundation/ +jQuery v 3.6.0 +Copyright OpenJS Foundation and other contributors, https://openjsf.org/ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the @@ -26,7 +26,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ****************************************** -The jQuery JavaScript Library v3.5.1 also includes Sizzle.js +The jQuery JavaScript Library v3.6.0 also includes Sizzle.js Sizzle.js includes the following license: diff --git a/src/jdk.jdeps/share/classes/com/sun/tools/classfile/TypeAnnotation.java b/src/jdk.jdeps/share/classes/com/sun/tools/classfile/TypeAnnotation.java index 5d591705d52ea4628caff04dc99c0fbda1788559..707cb8315402ffbf122198bd514812be56c67bda 100644 --- a/src/jdk.jdeps/share/classes/com/sun/tools/classfile/TypeAnnotation.java +++ b/src/jdk.jdeps/share/classes/com/sun/tools/classfile/TypeAnnotation.java @@ -130,7 +130,7 @@ public class TypeAnnotation { break; // class extends or implements clause case CLASS_EXTENDS: - position.type_index = cr.readUnsignedShort();; + position.type_index = cr.readUnsignedShort(); break; // throws case THROWS: diff --git a/src/jdk.jdi/share/classes/com/sun/tools/example/debug/tty/Commands.java b/src/jdk.jdi/share/classes/com/sun/tools/example/debug/tty/Commands.java index 15091d310d5aa402e3538545233824832df9dac9..121038a6d72e1630fdfd82c781e2022149c3a4ea 100644 --- a/src/jdk.jdi/share/classes/com/sun/tools/example/debug/tty/Commands.java +++ b/src/jdk.jdi/share/classes/com/sun/tools/example/debug/tty/Commands.java @@ -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 @@ -501,7 +501,7 @@ class Commands { void commandThreadGroup(StringTokenizer t) { if (!t.hasMoreTokens()) { - MessageOutput.println("Threadgroup name not specified."); + ThreadInfo.setThreadGroup(null); // reset to default (top level ThreadGroup) return; } String name = t.nextToken(); diff --git a/src/jdk.jdi/share/classes/com/sun/tools/example/debug/tty/TTY.java b/src/jdk.jdi/share/classes/com/sun/tools/example/debug/tty/TTY.java index 6e1ddcb1b846f091579f655af2e45bee8e50947a..9373bc9e0e037e5cf94eb15628d897144cbee40a 100644 --- a/src/jdk.jdi/share/classes/com/sun/tools/example/debug/tty/TTY.java +++ b/src/jdk.jdi/share/classes/com/sun/tools/example/debug/tty/TTY.java @@ -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 @@ -993,6 +993,8 @@ public class TTY implements EventNotifier { token.startsWith("-ss") || token.startsWith("-oss") ) { javaArgs = addArgument(javaArgs, token); + } else if (token.startsWith("-R")) { + javaArgs = addArgument(javaArgs, token.substring(2)); } else if (token.equals("-tclassic")) { usageError("Classic VM no longer supported."); return; diff --git a/src/jdk.jdi/share/classes/com/sun/tools/example/debug/tty/TTYResources.java b/src/jdk.jdi/share/classes/com/sun/tools/example/debug/tty/TTYResources.java index 8ba3c42c83ad47f587d963f7614f70f2bbdccbc2..e7090c8c8c827e4e2473365f79c10caf622f5fb3 100644 --- a/src/jdk.jdi/share/classes/com/sun/tools/example/debug/tty/TTYResources.java +++ b/src/jdk.jdi/share/classes/com/sun/tools/example/debug/tty/TTYResources.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 @@ -312,7 +312,6 @@ public class TTYResources extends java.util.ListResourceBundle { {"Thread has been resumed", "Thread has been resumed"}, {"Thread not suspended", "Thread not suspended"}, {"thread group number description name", "{0,number,integer}. {1} {2}"}, - {"Threadgroup name not specified.", "Threadgroup name not specified."}, {" option not valid until the VM is started with the run command", " option not valid until the VM is started with the run command"}, {"Threads must be suspended", "Threads must be suspended"}, @@ -354,7 +353,7 @@ public class TTYResources extends java.util.ListResourceBundle { "\n" + "run [class [args]] -- start execution of application's main class\n" + "\n" + - "threads [threadgroup] -- list threads\n" + + "threads [threadgroup] -- list threads in threadgroup. Use current threadgroup if none specified.\n" + "thread -- set default thread\n" + "suspend [thread id(s)] -- suspend threads (default: all)\n" + "resume [thread id(s)] -- resume threads (default: all)\n" + @@ -377,7 +376,8 @@ public class TTYResources extends java.util.ListResourceBundle { "fields -- list a class's fields\n" + "\n" + "threadgroups -- list threadgroups\n" + - "threadgroup -- set current threadgroup\n" + + "threadgroup -- set current threadgroup to \n" + + "threadgroup -- set current threadgroup back to the top level threadgroup\n" + "\n" + "stop [go|thread] [] \n" + " -- set a breakpoint\n" + @@ -477,8 +477,9 @@ public class TTYResources extends java.util.ListResourceBundle { " -dbgtrace [flags] print info for debugging {0}\n" + " -tclient run the application in the HotSpot(TM) Client Compiler\n" + " -tserver run the application in the HotSpot(TM) Server Compiler\n" + + " -R
A getAnnotation(Class annotationClass) { - Objects.requireNonNull(annotationClass); + Objects.requireNonNull(annotationClass, "annotationClass"); return platformEventType.getAnnotation(annotationClass); } @@ -198,7 +198,7 @@ public final class EventType { * {@code Registered(false)}, but not manually registered */ public static EventType getEventType(Class eventClass) { - Objects.requireNonNull(eventClass); + Objects.requireNonNull(eventClass, "eventClass"); Utils.ensureValidEventSubclass(eventClass); JVMSupport.ensureWithInternalError(); return MetadataRepository.getInstance().getEventType(eventClass); diff --git a/src/jdk.jfr/share/classes/jdk/jfr/FlightRecorder.java b/src/jdk.jfr/share/classes/jdk/jfr/FlightRecorder.java index 398fe2eb13a5938d60ef9227e06eaa3e503f180c..27cc96507ee6eeaa156446f3082be099eb1b36db 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/FlightRecorder.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/FlightRecorder.java @@ -120,7 +120,7 @@ public final class FlightRecorder { * does not have {@code FlightRecorderPermission("registerEvent")} */ public static void register(Class eventClass) { - Objects.requireNonNull(eventClass); + Objects.requireNonNull(eventClass, "eventClass"); if (JVMSupport.isNotAvailable()) { return; } @@ -142,7 +142,7 @@ public final class FlightRecorder { * does not have {@code FlightRecorderPermission("registerEvent")} */ public static void unregister(Class eventClass) { - Objects.requireNonNull(eventClass); + Objects.requireNonNull(eventClass, "eventClass"); if (JVMSupport.isNotAvailable()) { return; } @@ -215,8 +215,8 @@ public final class FlightRecorder { * does not have {@code FlightRecorderPermission("registerEvent")} */ public static void addPeriodicEvent(Class eventClass, Runnable hook) throws SecurityException { - Objects.requireNonNull(eventClass); - Objects.requireNonNull(hook); + Objects.requireNonNull(eventClass, "eventClass"); + Objects.requireNonNull(hook, "hook"); if (JVMSupport.isNotAvailable()) { return; } @@ -237,7 +237,7 @@ public final class FlightRecorder { * does not have {@code FlightRecorderPermission("registerEvent")} */ public static boolean removePeriodicEvent(Runnable hook) throws SecurityException { - Objects.requireNonNull(hook); + Objects.requireNonNull(hook, "hook"); Utils.checkRegisterPermission(); if (JVMSupport.isNotAvailable()) { return false; @@ -274,7 +274,7 @@ public final class FlightRecorder { * {@code FlightRecorderPermission("accessFlightRecorder")} */ public static void addListener(FlightRecorderListener changeListener) { - Objects.requireNonNull(changeListener); + Objects.requireNonNull(changeListener, "changeListener"); Utils.checkAccessFlightRecorder(); if (JVMSupport.isNotAvailable()) { return; @@ -298,7 +298,7 @@ public final class FlightRecorder { * otherwise */ public static boolean removeListener(FlightRecorderListener changeListener) { - Objects.requireNonNull(changeListener); + Objects.requireNonNull(changeListener, "changeListener"); Utils.checkAccessFlightRecorder(); if (JVMSupport.isNotAvailable()) { return false; diff --git a/src/jdk.jfr/share/classes/jdk/jfr/FlightRecorderPermission.java b/src/jdk.jfr/share/classes/jdk/jfr/FlightRecorderPermission.java index 7b89ddf02c8b547bea2c8f75fc1a1fe850bdb7fc..a76122c929a786f3b2f9815218582761d408f102 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/FlightRecorderPermission.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/FlightRecorderPermission.java @@ -220,7 +220,7 @@ public final class FlightRecorderPermission extends java.security.BasicPermissio * @throws IllegalArgumentException if {@code name} is empty or not valid */ public FlightRecorderPermission(String name) { - super(Objects.requireNonNull(name)); + super(Objects.requireNonNull(name, "name")); if (!name.equals(Utils.ACCESS_FLIGHT_RECORDER) && !name.equals(Utils.REGISTER_EVENT)) { throw new IllegalArgumentException("name: " + name); } diff --git a/src/jdk.jfr/share/classes/jdk/jfr/Recording.java b/src/jdk.jfr/share/classes/jdk/jfr/Recording.java index 4f07bca6641192b235c02c1a6a50d1f5706a47ad..c5c01f4370c525fbbc837352d3c10de94b53907f 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/Recording.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/Recording.java @@ -70,7 +70,8 @@ public final class Recording implements Closeable { @Override public EventSettings with(String name, String value) { - Objects.requireNonNull(value); + Objects.requireNonNull(name, "name"); + Objects.requireNonNull(value, "value"); recording.setSetting(identifier + "#" + name, value); return this; } @@ -101,7 +102,7 @@ public final class Recording implements Closeable { * @see jdk.jfr */ public Recording(Map settings) { - Objects.requireNonNull(settings); + Objects.requireNonNull(settings, "settings"); Map sanitized = Utils.sanitizeNullFreeStringMap(settings); PlatformRecorder r = FlightRecorder.getFlightRecorder().getInternal(); synchronized (r) { @@ -155,7 +156,7 @@ public final class Recording implements Closeable { * @see Configuration */ public Recording(Configuration configuration) { - this(configuration.getSettings()); + this(Objects.requireNonNull(configuration, "configuration").getSettings()); } /** @@ -187,7 +188,7 @@ public final class Recording implements Closeable { * @throws IllegalStateException if the recording is not it the {@code NEW} state */ public void scheduleStart(Duration delay) { - Objects.requireNonNull(delay); + Objects.requireNonNull(delay, "delay"); internal.scheduleStart(delay); } @@ -318,7 +319,7 @@ public final class Recording implements Closeable { * @param settings the settings to set, not {@code null} */ public void setSettings(Map settings) { - Objects.requireNonNull(settings); + Objects.requireNonNull(settings, "settings"); Map sanitized = Utils.sanitizeNullFreeStringMap(settings); internal.setSettings(sanitized); } @@ -375,7 +376,7 @@ public final class Recording implements Closeable { * have {@code FilePermission} to write to the destination path */ public void dump(Path destination) throws IOException { - Objects.requireNonNull(destination); + Objects.requireNonNull(destination, "destination"); internal.dump(new WriteableUserPath(destination)); } @@ -509,7 +510,7 @@ public final class Recording implements Closeable { * @throws IllegalStateException if the recording is in {@code CLOSED} state */ public void setName(String name) { - Objects.requireNonNull(name); + Objects.requireNonNull(name, "name"); internal.setName(name); } @@ -619,7 +620,7 @@ public final class Recording implements Closeable { * @see EventType */ public EventSettings enable(String name) { - Objects.requireNonNull(name); + Objects.requireNonNull(name, "name"); RecordingSettings rs = new RecordingSettings(this, name); rs.with("enabled", "true"); return rs; @@ -640,7 +641,7 @@ public final class Recording implements Closeable { * */ public EventSettings disable(String name) { - Objects.requireNonNull(name); + Objects.requireNonNull(name, "name"); RecordingSettings rs = new RecordingSettings(this, name); rs.with("enabled", "false"); return rs; @@ -657,7 +658,7 @@ public final class Recording implements Closeable { * @return an event setting for further configuration, not {@code null} */ public EventSettings enable(Class eventClass) { - Objects.requireNonNull(eventClass); + Objects.requireNonNull(eventClass, "eventClass"); RecordingSettings rs = new RecordingSettings(this, eventClass); rs.with("enabled", "true"); return rs; @@ -675,7 +676,7 @@ public final class Recording implements Closeable { * */ public EventSettings disable(Class eventClass) { - Objects.requireNonNull(eventClass); + Objects.requireNonNull(eventClass, "eventClass"); RecordingSettings rs = new RecordingSettings(this, eventClass); rs.with("enabled", "false"); return rs; diff --git a/src/jdk.jfr/share/classes/jdk/jfr/ValueDescriptor.java b/src/jdk.jfr/share/classes/jdk/jfr/ValueDescriptor.java index 26e523ed40cb97bc81f6ad460f4b2e5594f139b1..7f517e07b61f8c0b46e164893079ae944a40ce88 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/ValueDescriptor.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/ValueDescriptor.java @@ -139,7 +139,9 @@ public final class ValueDescriptor { ValueDescriptor(Class type, String name, List annotations, boolean allowArray) { - Objects.requireNonNull(annotations); + Objects.requireNonNull(type, "type"); + Objects.requireNonNull(name, "name"); + Objects.requireNonNull(annotations, "annotations"); Utils.checkRegisterPermission(); if (!allowArray) { if (type.isArray()) { @@ -271,7 +273,7 @@ public final class ValueDescriptor { * directly present, else {@code null} */ public A getAnnotation(Class annotationType) { - Objects.requireNonNull(annotationType); + Objects.requireNonNull(annotationType, "annotationType"); return annotationConstruct.getAnnotation(annotationType); } diff --git a/src/jdk.jfr/share/classes/jdk/jfr/consumer/EventStream.java b/src/jdk.jfr/share/classes/jdk/jfr/consumer/EventStream.java index 8b55f669ef28a7100fb2a05ba13eab394925c98a..895c1f2d4a408d1ff5315b8555763f01d062b56e 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/consumer/EventStream.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/consumer/EventStream.java @@ -149,7 +149,7 @@ public interface EventStream extends AutoCloseable { * files in the directory. */ public static EventStream openRepository(Path directory) throws IOException { - Objects.requireNonNull(directory); + Objects.requireNonNull(directory, "directory"); @SuppressWarnings("removal") AccessControlContext acc = AccessController.getContext(); return new EventDirectoryStream( @@ -179,6 +179,7 @@ public interface EventStream extends AutoCloseable { */ @SuppressWarnings("removal") static EventStream openFile(Path file) throws IOException { + Objects.requireNonNull(file, "file"); return new EventFileStream(AccessController.getContext(), file); } diff --git a/src/jdk.jfr/share/classes/jdk/jfr/consumer/RecordedObject.java b/src/jdk.jfr/share/classes/jdk/jfr/consumer/RecordedObject.java index 277c9899def5b8657f9ef3c407b5d96dc0a49c86..14d5ce4985fb79c0f05887fffdb9a42fda883f5a 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/consumer/RecordedObject.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/consumer/RecordedObject.java @@ -247,7 +247,7 @@ public class RecordedObject { } private Object getValue(String name, boolean allowUnsigned) { - Objects.requireNonNull(name); + Objects.requireNonNull(name, "name"); int index = 0; for (ValueDescriptor v : objectContext.fields) { if (name.equals(v.getName())) { @@ -329,14 +329,14 @@ public class RecordedObject { return v; } } - throw new IllegalArgumentException("\"Attempt to get unknown field \"" + name + "\""); + throw new IllegalArgumentException("Attempt to get unknown field \"" + name + "\""); } // Gets a value, but checks that type and name is correct first // This is to prevent a call to getString on a thread field, that is // null to succeed. private T getTypedValue(String name, String typeName) { - Objects.requireNonNull(name); + Objects.requireNonNull(name, "name"); // Validate name and type first getValueDescriptor(objectContext.fields, name, typeName); return getValue(name); diff --git a/src/jdk.jfr/share/classes/jdk/jfr/consumer/RecordingFile.java b/src/jdk.jfr/share/classes/jdk/jfr/consumer/RecordingFile.java index 15501bc6880a0d82a7ee61ccf56566e45d05b629..d52449f4d745513ecbdb23d0deea641deca419e6 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/consumer/RecordingFile.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/consumer/RecordingFile.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 @@ -34,15 +34,19 @@ import java.nio.file.Path; import java.util.ArrayList; import java.util.HashSet; import java.util.List; - +import java.util.Objects; +import java.util.function.Predicate; import jdk.jfr.EventType; import jdk.jfr.internal.MetadataDescriptor; import jdk.jfr.internal.Type; +import jdk.jfr.internal.consumer.ChunkParser.ParserConfiguration; +import jdk.jfr.internal.consumer.ParserFilter; import jdk.jfr.internal.consumer.ChunkHeader; import jdk.jfr.internal.consumer.ChunkParser; import jdk.jfr.internal.consumer.FileAccess; import jdk.jfr.internal.consumer.ParserState; import jdk.jfr.internal.consumer.RecordingInput; +import jdk.jfr.internal.consumer.filter.ChunkWriter; /** * A recording file. @@ -56,6 +60,7 @@ import jdk.jfr.internal.consumer.RecordingInput; public final class RecordingFile implements Closeable { private final ParserState parserState = new ParserState(); + private final ChunkWriter chunkWriter; private boolean isLastEventInChunk; private final File file; private RecordingInput input; @@ -75,8 +80,18 @@ public final class RecordingFile implements Closeable { * {@code checkRead} method denies read access to the file. */ public RecordingFile(Path file) throws IOException { + Objects.requireNonNull(file, "file"); this.file = file.toFile(); this.input = new RecordingInput(this.file, FileAccess.UNPRIVILEGED); + this.chunkWriter = null; + findNext(); + } + + // Only used by RecordingFile::write(Path, Predicate) + private RecordingFile(ChunkWriter chunkWriter) throws IOException { + this.file = null; // not used + this.input = chunkWriter.getInput(); + this.chunkWriter = chunkWriter; findNext(); } @@ -199,6 +214,34 @@ public final class RecordingFile implements Closeable { } } + /** + * Filter out events and write them to a new file. + * + * @param destination path where the new file should be written, not + * {@code null} + * + * @param filter filter that determines if an event should be included, not + * {@code null} + * @throws IOException if an I/O error occurred, it's not a Flight + * Recorder file or a version of a JFR file that can't + * be parsed + * + * @throws SecurityException if a security manager exists and its + * {@code checkWrite} method denies write access to the + * file + */ + public void write(Path destination, Predicate filter) throws IOException { + Objects.requireNonNull(destination, "destination"); + Objects.requireNonNull(filter, "filter"); + try (ChunkWriter cw = new ChunkWriter(file.toPath(), destination, filter)) { + try (RecordingFile rf = new RecordingFile(cw)) { + while (rf.hasMoreEvents()) { + rf.readEvent(); + } + } + } + } + /** * Returns a list of all events in a file. *

@@ -237,15 +280,15 @@ public final class RecordingFile implements Closeable { return isLastEventInChunk; } - // either sets next to an event or sets eof to true private void findNext() throws IOException { while (nextEvent == null) { if (chunkParser == null) { - chunkParser = new ChunkParser(input, parserState); + chunkParser = createChunkParser(); } else if (!chunkParser.isLastChunk()) { - chunkParser = chunkParser.nextChunkParser(); + chunkParser = nextChunkParser(); } else { + endChunkParser(); eof = true; return; } @@ -256,6 +299,36 @@ public final class RecordingFile implements Closeable { } } + private ChunkParser createChunkParser() throws IOException { + if (chunkWriter != null) { + boolean reuse = true; + boolean ordered = false; + ParserConfiguration pc = new ParserConfiguration(0, Long.MAX_VALUE, reuse, ordered, ParserFilter.ACCEPT_ALL, chunkWriter); + ChunkParser chunkParser = new ChunkParser(chunkWriter.getInput(), pc, new ParserState()); + chunkWriter.beginChunk(chunkParser.getHeader()); + return chunkParser; + } else { + return new ChunkParser(input, parserState); + } + } + + private void endChunkParser() throws IOException { + if (chunkWriter != null) { + chunkWriter.endChunk(chunkParser.getHeader()); + } + } + + private ChunkParser nextChunkParser() throws IOException { + if (chunkWriter != null) { + chunkWriter.endChunk(chunkParser.getHeader()); + } + ChunkParser next = chunkParser.nextChunkParser(); + if (chunkWriter != null) { + chunkWriter.beginChunk(next.getHeader()); + } + return next; + } + private void ensureOpen() throws IOException { if (input == null) { throw new IOException("Stream Closed"); diff --git a/src/jdk.jfr/share/classes/jdk/jfr/consumer/RecordingStream.java b/src/jdk.jfr/share/classes/jdk/jfr/consumer/RecordingStream.java index 643471969487af15ffc1cee9d13c9abe39c36940..475d9ce760ad8e2b922eeb8ed850fd0133763942 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/consumer/RecordingStream.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/consumer/RecordingStream.java @@ -97,6 +97,10 @@ public final class RecordingStream implements AutoCloseable, EventStream { * {@code FlightRecorderPermission("accessFlightRecorder")} */ public RecordingStream() { + this(Map.of()); + } + + private RecordingStream(Map settings) { Utils.checkAccessFlightRecorder(); @SuppressWarnings("removal") AccessControlContext acc = AccessController.getContext(); @@ -117,6 +121,9 @@ public final class RecordingStream implements AutoCloseable, EventStream { this.recording.close(); throw new IllegalStateException(ioe.getMessage()); } + if (!settings.isEmpty()) { + recording.setSettings(settings); + } } private List configurations() { @@ -148,8 +155,7 @@ public final class RecordingStream implements AutoCloseable, EventStream { * @see Configuration */ public RecordingStream(Configuration configuration) { - this(); - recording.setSettings(configuration.getSettings()); + this(Objects.requireNonNull(configuration, "configuration").getSettings()); } /** diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/AbstractEventStream.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/AbstractEventStream.java index 3feb350eb25a7102b8e5d9831fcb52bc28037685..f3e6090149fa9b3cfae5423147c3fc65fd65f959 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/AbstractEventStream.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/AbstractEventStream.java @@ -111,7 +111,7 @@ public abstract class AbstractEventStream implements EventStream { @Override public final void setStartTime(Instant startTime) { - Objects.requireNonNull(startTime); + Objects.requireNonNull(startTime, "startTime"); synchronized (streamConfiguration) { if (streamConfiguration.started) { throw new IllegalStateException("Stream is already started"); @@ -125,7 +125,7 @@ public abstract class AbstractEventStream implements EventStream { @Override public final void setEndTime(Instant endTime) { - Objects.requireNonNull(endTime); + Objects.requireNonNull(endTime, "endTime"); synchronized (streamConfiguration) { if (streamConfiguration.started) { throw new IllegalStateException("Stream is already started"); @@ -136,38 +136,38 @@ public abstract class AbstractEventStream implements EventStream { @Override public final void onEvent(Consumer action) { - Objects.requireNonNull(action); + Objects.requireNonNull(action, "action"); streamConfiguration.addEventAction(action); } @Override public final void onEvent(String eventName, Consumer action) { - Objects.requireNonNull(eventName); - Objects.requireNonNull(action); + Objects.requireNonNull(eventName, "eventName"); + Objects.requireNonNull(action, "action"); streamConfiguration.addEventAction(eventName, action); } @Override public final void onFlush(Runnable action) { - Objects.requireNonNull(action); + Objects.requireNonNull(action, "action"); streamConfiguration.addFlushAction(action); } @Override public final void onClose(Runnable action) { - Objects.requireNonNull(action); + Objects.requireNonNull(action, "action"); streamConfiguration.addCloseAction(action); } @Override public final void onError(Consumer action) { - Objects.requireNonNull(action); + Objects.requireNonNull(action, "action"); streamConfiguration.addErrorAction(action); } @Override public final boolean remove(Object action) { - Objects.requireNonNull(action); + Objects.requireNonNull(action, "action"); return streamConfiguration.remove(action); } @@ -178,7 +178,7 @@ public abstract class AbstractEventStream implements EventStream { @Override public final void awaitTermination(Duration timeout) throws InterruptedException { - Objects.requireNonNull(timeout); + Objects.requireNonNull(timeout, "timeout"); if (timeout.isNegative()) { throw new IllegalArgumentException("timeout value is negative"); } @@ -298,7 +298,7 @@ public abstract class AbstractEventStream implements EventStream { @Override public void onMetadata(Consumer action) { - Objects.requireNonNull(action); + Objects.requireNonNull(action, "action"); synchronized (streamConfiguration) { if (streamConfiguration.started) { throw new IllegalStateException("Stream is already started"); diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/ChunkHeader.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/ChunkHeader.java index 95aa47a34bbcf7ad5157d0f5a1b5795c7adbbba3..550878888cd74e936a627906dc294c5abc7b9aa1 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/ChunkHeader.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/ChunkHeader.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 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 @@ -34,9 +34,9 @@ import jdk.jfr.internal.MetadataDescriptor; import jdk.jfr.internal.Utils; public final class ChunkHeader { - static final long HEADER_SIZE = 68; + public static final long HEADER_SIZE = 68; static final byte UPDATING_CHUNK_HEADER = (byte) 255; - static final long CHUNK_SIZE_POSITION = 8; + public static final long CHUNK_SIZE_POSITION = 8; static final long DURATION_NANOS_POSITION = 40; static final long FILE_STATE_POSITION = 64; static final long FLAG_BYTE_POSITION = 67; @@ -92,10 +92,10 @@ public final class ChunkHeader { } long c = input.readRawLong(); // chunk size Logger.log(LogTag.JFR_SYSTEM_PARSER, LogLevel.INFO, "Chunk: chunkSize=" + c); - input.readRawLong(); // constant pool position - Logger.log(LogTag.JFR_SYSTEM_PARSER, LogLevel.INFO, "Chunk: constantPoolPosition=" + constantPoolPosition); - input.readRawLong(); // metadata position - Logger.log(LogTag.JFR_SYSTEM_PARSER, LogLevel.INFO, "Chunk: metadataPosition=" + metadataPosition); + long cp = input.readRawLong(); // constant pool position + Logger.log(LogTag.JFR_SYSTEM_PARSER, LogLevel.INFO, "Chunk: constantPoolPosition=" + cp); + long mp = input.readRawLong(); // metadata position + Logger.log(LogTag.JFR_SYSTEM_PARSER, LogLevel.INFO, "Chunk: metadataPosition=" + mp); chunkStartNanos = input.readRawLong(); // nanos since epoch Logger.log(LogTag.JFR_SYSTEM_PARSER, LogLevel.INFO, "Chunk: startNanos=" + chunkStartNanos); durationNanos = input.readRawLong(); // duration nanos, not used @@ -109,14 +109,19 @@ public final class ChunkHeader { input.position(absoluteEventStart); } + private byte readFileState() throws IOException { + byte fs; + input.positionPhysical(absoluteChunkStart + FILE_STATE_POSITION); + while ((fs = input.readPhysicalByte()) == UPDATING_CHUNK_HEADER) { + Utils.takeNap(1); + input.positionPhysical(absoluteChunkStart + FILE_STATE_POSITION); + } + return fs; + } + public void refresh() throws IOException { while (true) { - byte fileState1; - input.positionPhysical(absoluteChunkStart + FILE_STATE_POSITION); - while ((fileState1 = input.readPhysicalByte()) == UPDATING_CHUNK_HEADER) { - Utils.takeNap(1); - input.positionPhysical(absoluteChunkStart + FILE_STATE_POSITION); - } + byte fileState1 = readFileState(); input.positionPhysical(absoluteChunkStart + CHUNK_SIZE_POSITION); long chunkSize = input.readPhysicalLong(); long constantPoolPosition = input.readPhysicalLong(); @@ -169,10 +174,9 @@ public final class ChunkHeader { } long pos = input.position(); try { - input.positionPhysical(absoluteChunkStart + FILE_STATE_POSITION); while (true) { - byte filestate = input.readPhysicalByte(); - if (filestate == 0) { + byte fileState = readFileState(); + if (fileState == 0) { finished = true; return; } @@ -243,7 +247,7 @@ public final class ChunkHeader { return constantPoolPosition; } - public long getMetataPosition() { + public long getMetadataPosition() { return metadataPosition; } public long getStartTicks() { diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/ChunkParser.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/ChunkParser.java index d698b3c52585fd381c897df63e9d8ea91d962074..9d88adcf478a24e01de6e816088ba1b143dc582d 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/ChunkParser.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/ChunkParser.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 @@ -41,6 +41,8 @@ import jdk.jfr.internal.LongMap; import jdk.jfr.internal.MetadataDescriptor; import jdk.jfr.internal.Type; import jdk.jfr.internal.Utils; +import jdk.jfr.internal.consumer.filter.CheckpointEvent; +import jdk.jfr.internal.consumer.filter.ChunkWriter; /** * Parses a chunk. @@ -48,24 +50,26 @@ import jdk.jfr.internal.Utils; */ public final class ChunkParser { - static final class ParserConfiguration { + public static final class ParserConfiguration { private final boolean reuse; private final boolean ordered; private final ParserFilter eventFilter; + private final ChunkWriter chunkWriter; long filterStart; long filterEnd; - ParserConfiguration(long filterStart, long filterEnd, boolean reuse, boolean ordered, ParserFilter filter) { + public ParserConfiguration(long filterStart, long filterEnd, boolean reuse, boolean ordered, ParserFilter filter, ChunkWriter chunkWriter) { this.filterStart = filterStart; this.filterEnd = filterEnd; this.reuse = reuse; this.ordered = ordered; this.eventFilter = filter; + this.chunkWriter = chunkWriter; } public ParserConfiguration() { - this(0, Long.MAX_VALUE, false, false, ParserFilter.ACCEPT_ALL); + this(0, Long.MAX_VALUE, false, false, ParserFilter.ACCEPT_ALL, null); } public boolean isOrdered() { @@ -73,7 +77,7 @@ public final class ChunkParser { } } - private enum CheckPointType { + private enum CheckpointType { // Checkpoint that finishes a flush segment FLUSH(1), // Checkpoint contains chunk header information in the first pool @@ -83,7 +87,7 @@ public final class ChunkParser { // Checkpoint contains thread related information THREAD(8); private final int mask; - private CheckPointType(int mask) { + private CheckpointType(int mask) { this.mask = mask; } @@ -113,13 +117,13 @@ public final class ChunkParser { this(input, new ParserConfiguration(), ps); } - ChunkParser(RecordingInput input, ParserConfiguration pc, ParserState ps) throws IOException { + public ChunkParser(RecordingInput input, ParserConfiguration pc, ParserState ps) throws IOException { this(new ChunkHeader(input), null, pc, ps); } private ChunkParser(ChunkParser previous, ParserState ps) throws IOException { this(new ChunkHeader(previous.input), previous, new ParserConfiguration(), ps); - } + } private ChunkParser(ChunkHeader header, ChunkParser previous, ParserConfiguration pc, ParserState ps) throws IOException { this.parserState = ps; @@ -199,7 +203,7 @@ public final class ChunkParser { return event; } long lastValid = absoluteChunkEnd; - long metadataPosition = chunkHeader.getMetataPosition(); + long metadataPosition = chunkHeader.getMetadataPosition(); long constantPosition = chunkHeader.getConstantPoolPosition(); chunkFinished = awaitUpdatedHeader(absoluteChunkEnd, configuration.filterEnd); if (chunkFinished) { @@ -208,7 +212,7 @@ public final class ChunkParser { } absoluteChunkEnd = chunkHeader.getEnd(); // Read metadata and constant pools for the next segment - if (chunkHeader.getMetataPosition() != metadataPosition) { + if (chunkHeader.getMetadataPosition() != metadataPosition) { Logger.log(LogTag.JFR_SYSTEM_PARSER, LogLevel.INFO, "Found new metadata in chunk. Rebuilding types and parsers"); this.previousMetadata = this.metadata; this.metadata = chunkHeader.readMetadata(previousMetadata); @@ -247,13 +251,23 @@ public final class ChunkParser { // Fast path RecordedEvent event = ep.parse(input); if (event != null) { + ChunkWriter chunkWriter = configuration.chunkWriter; + if (chunkWriter != null) { + if (chunkWriter.accept(event)) { + chunkWriter.writeEvent(pos, input.position()); + input.position(pos); + input.readInt(); // size + input.readLong(); // type + chunkWriter.touch(ep.parseReferences(input)); + } + } input.position(pos + size); return event; } // Not accepted by filter } else { if (typeId == 1) { // checkpoint event - if (CheckPointType.FLUSH.is(parseCheckpointType())) { + if (CheckpointType.FLUSH.is(parseCheckpointType())) { input.position(pos + size); return FLUSH_MARKER; } @@ -303,6 +317,10 @@ public final class ChunkParser { long delta = -1; boolean logTrace = Logger.shouldLog(LogTag.JFR_SYSTEM_PARSER, LogLevel.TRACE); while (thisCP != abortCP && delta != 0) { + CheckpointEvent cp = null; + if (configuration.chunkWriter != null) { + cp = configuration.chunkWriter.newCheckpointEvent(thisCP); + } input.position(thisCP); lastCP = thisCP; int size = input.readInt(); // size @@ -333,7 +351,7 @@ public final class ChunkParser { throw new IOException( "Error parsing constant pool type " + getName(id) + " at position " + input.position() + " at check point between [" + lastCP + ", " + (lastCP + size) + "]"); } - ConstantMap pool = new ConstantMap(ObjectFactory.create(type, timeConverter), type.getName()); + ConstantMap pool = new ConstantMap(ObjectFactory.create(type, timeConverter), type); lookup = new ConstantLookup(pool, type); constantLookups.put(type.getId(), lookup); } @@ -350,6 +368,7 @@ public final class ChunkParser { Logger.log(LogTag.JFR_SYSTEM_PARSER, LogLevel.TRACE, "Constant Pool " + i + ": " + type.getName()); } for (int j = 0; j < count; j++) { + long position = input.position(); long key = input.readLong(); Object resolved = lookup.getPreviousResolved(key); if (resolved == null) { @@ -361,6 +380,12 @@ public final class ChunkParser { logConstant(key, resolved, true); lookup.getLatestPool().putResolved(key, resolved); } + if (cp != null) { + input.position(position); + input.readLong(); + Object refs = parser.parseReferences(input); + cp.addEntry(type, key, position, input.position(), refs); + } } } catch (Exception e) { throw new IOException("Error parsing constant pool type " + getName(id) + " at position " + input.position() + " at check point between [" + lastCP + ", " + (lastCP + size) + "]", @@ -436,7 +461,7 @@ public final class ChunkParser { return chunkHeader.isLastChunk(); } - ChunkParser newChunkParser() throws IOException { + public ChunkParser newChunkParser() throws IOException { return new ChunkParser(this, parserState); } @@ -488,4 +513,8 @@ public final class ChunkParser { }); } } + + public ChunkHeader getHeader() { + return chunkHeader; + } } diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/CompositeParser.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/CompositeParser.java new file mode 100644 index 0000000000000000000000000000000000000000..72a9bf0ec668562b9b6de157ce2302f867e2150e --- /dev/null +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/CompositeParser.java @@ -0,0 +1,74 @@ +/* + * 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package jdk.jfr.internal.consumer; + +import java.io.IOException; +import java.util.ArrayList; + +public final class CompositeParser extends Parser { + final Parser[] parsers; + + public CompositeParser(Parser[] valueParsers) { + this.parsers = valueParsers; + } + + @Override + public Object parse(RecordingInput input) throws IOException { + final Object[] values = new Object[parsers.length]; + for (int i = 0; i < values.length; i++) { + values[i] = parsers[i].parse(input); + } + return values; + } + + @Override + public void skip(RecordingInput input) throws IOException { + for (int i = 0; i < parsers.length; i++) { + parsers[i].skip(input); + } + } + + @Override + public Object parseReferences(RecordingInput input) throws IOException { + return parseReferences(input, parsers); + } + + static Object parseReferences(RecordingInput input, Parser[] parsers) throws IOException { + ArrayList refs = new ArrayList<>(parsers.length); + for (int i = 0; i < parsers.length; i++) { + Object ref = parsers[i].parseReferences(input); + if (ref != null) { + refs.add(ref); + } + } + if (refs.isEmpty()) { + return null; + } + if (refs.size() == 1) { + return refs.get(0); + } + return refs.toArray(); + } +} \ No newline at end of file diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/ConstantLookup.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/ConstantLookup.java index 4ae6cde058b2dd55df3df1444e8a1a49519f4a8c..e4c5435cc30276e5ee387531d0fc490f41088f56 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/ConstantLookup.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/ConstantLookup.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 @@ -28,7 +28,7 @@ package jdk.jfr.internal.consumer; import jdk.jfr.internal.Type; final class ConstantLookup { - private final Type type; + final Type type; private ConstantMap current; private ConstantMap previous = ConstantMap.EMPTY; @@ -47,7 +47,7 @@ final class ConstantLookup { public void newPool() { previous = current; - current = new ConstantMap(current.factory, current.name); + current = new ConstantMap(current.factory, current.type); } public Object getPreviousResolved(long key) { diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/ConstantMap.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/ConstantMap.java index 55b60b7240f1ec9fa4201a36f7cc8556f6e7a58b..79d001fcac452111c54a3f48c8b53c98cf29c005 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/ConstantMap.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/ConstantMap.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 @@ -30,6 +30,7 @@ import jdk.jfr.internal.LogTag; import jdk.jfr.internal.Logger; import jdk.jfr.internal.LongMap; +import jdk.jfr.internal.Type; /** * Holds mapping between a set of keys and their corresponding object. @@ -38,49 +39,23 @@ import jdk.jfr.internal.LongMap; * {@link ObjectFactory} can be supplied which will instantiate a typed object. */ final class ConstantMap { - private static final int RESOLUTION_FINISHED = 0; private static final int RESOLUTION_STARTED = 1; public static final ConstantMap EMPTY = new ConstantMap(); - // A temporary placeholder, so objects can - // reference themselves (directly, or indirectly), - // when making a transition from numeric id references - // to normal Java references. - private static final class Reference { - private final long key; - private final ConstantMap pool; - - Reference(ConstantMap pool, long key) { - this.pool = pool; - this.key = key; - } - - Object resolve() { - return pool.get(key); - } - - @Override - public String toString() { - return "ref: " + pool.name + "[" + key + "]"; - } - } - final ObjectFactory factory; - final String name; - + final Type type; private final LongMap objects; - private boolean resolving; private boolean allResolved; private ConstantMap() { - this(null, ""); + this(null, null); allResolved = true; } - ConstantMap(ObjectFactory factory, String name) { - this.name = name; + ConstantMap(ObjectFactory factory, Type type) { + this.type = type; this.objects = new LongMap<>(2); this.factory = factory; } @@ -100,7 +75,7 @@ final class ConstantMap { if (value == null) { // unless id is 0 which is used to represent null if (id != 0) { - Logger.log(LogTag.JFR_SYSTEM_PARSER, LogLevel.INFO, "Missing object id=" + id + " in pool " + name + ". All ids should reference an object"); + Logger.log(LogTag.JFR_SYSTEM_PARSER, LogLevel.INFO, "Missing object id=" + id + " in pool " + getName() + ". All ids should reference an object"); } return null; } @@ -174,7 +149,12 @@ final class ConstantMap { } public String getName() { - return name; + return type == null ? "" : type.getName(); + } + + // Can be null + public Type getType() { + return type; } public Object getResolved(long id) { @@ -189,4 +169,8 @@ final class ConstantMap { public void setAllResolved(boolean allResolved) { this.allResolved = allResolved; } + + public LongMap getObjects() { + return objects; + } } diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/Dispatcher.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/Dispatcher.java index e8a565deb5d0ebdea99e993b7fff15bd79f28149..094e7d9538bbdcc4c939b85ec230bbbe9b5ffc0b 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/Dispatcher.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/Dispatcher.java @@ -85,7 +85,7 @@ final class Dispatcher { this.errorActions = c.errorActions.toArray(new Consumer[0]); this.metadataActions = c.metadataActions.toArray(new Consumer[0]); this.dispatchers = c.eventActions.toArray(new EventDispatcher[0]); - this.parserConfiguration = new ParserConfiguration(0, Long.MAX_VALUE, c.reuse, c.ordered, buildFilter(dispatchers)); + this.parserConfiguration = new ParserConfiguration(0, Long.MAX_VALUE, c.reuse, c.ordered, buildFilter(dispatchers), null); this.startTime = c.startTime; this.endTime = c.endTime; this.startNanos = c.startNanos; diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/EventFileStream.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/EventFileStream.java index 89402f623086925a5a0473b10d3fcae1876efa62..bbd06c8b8a83b5738781acc7e96f8d974d8b92a8 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/EventFileStream.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/EventFileStream.java @@ -46,10 +46,9 @@ public final class EventFileStream extends AbstractEventStream { private ChunkParser currentParser; private RecordedEvent[] cacheSorted; - public EventFileStream(@SuppressWarnings("removal") AccessControlContext acc, Path path) throws IOException { + public EventFileStream(@SuppressWarnings("removal") AccessControlContext acc, Path file) throws IOException { super(acc, null, Collections.emptyList()); - Objects.requireNonNull(path); - this.input = new RecordingInput(path.toFile(), FileAccess.UNPRIVILEGED); + this.input = new RecordingInput(file.toFile(), FileAccess.UNPRIVILEGED); } @Override diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/EventParser.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/EventParser.java index 56ac81d269cb8c704bd614a6ed2f0451abe07083..9ed091704e57a3782f5c57a1c71c894d9d27176b 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/EventParser.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/EventParser.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 @@ -28,7 +28,9 @@ package jdk.jfr.internal.consumer; import static jdk.jfr.internal.EventInstrumentation.FIELD_DURATION; import java.io.IOException; +import java.util.ArrayList; import java.util.List; +import java.util.function.Predicate; import jdk.jfr.EventType; import jdk.jfr.ValueDescriptor; @@ -154,6 +156,11 @@ final class EventParser extends Parser { return PRIVATE_ACCESS.newRecordedEvent(objectContext, values, startTicks, endTicks); } + @Override + public Object parseReferences(RecordingInput input) throws IOException { + return CompositeParser.parseReferences(input, parsers); + } + @Override public void skip(RecordingInput input) throws IOException { throw new InternalError("Should not call this method. More efficient to read event size and skip ahead"); diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/Parser.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/Parser.java index 49cbc13bdcbbb9bfac92ed1382bc2442e61358da..b1e0f27ff287544d43c8e38190bbcf4c2f1e143c 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/Parser.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/Parser.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,12 +35,28 @@ abstract class Parser { * Parses data from a {@link RecordingInput} and return an object. * * @param input input to read from - * @return an object + * @return an {@code Object}, an {@code Object[]}, or {@code null} * @throws IOException if operation couldn't be completed due to I/O * problems */ public abstract Object parse(RecordingInput input) throws IOException; + /** + * Parses data from a {@link RecordingInput} to find references to constants. If + * data is not a reference, {@code null} is returned. + *

+ * @implSpec The default implementation of this method skips data and returns + * {@code Object}. + * + * @param input input to read from, not {@code null} + * @return a {@code Reference}, a {@code Reference[]}, or {@code null} + * @throws IOException if operation couldn't be completed due to I/O problems + */ + public Object parseReferences(RecordingInput input) throws IOException { + skip(input); + return null; + } + /** * Skips data that would usually be by parsed the {@link #parse(RecordingInput)} method. * diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/ParserFactory.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/ParserFactory.java index ff72a5547440f178cd94a56df1a4a51f78a1c187..51e10a5219e0642cfaab0ef7f4f6f77d89fd5415 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/ParserFactory.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/ParserFactory.java @@ -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. * 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,7 +101,7 @@ final class ParserFactory { if (constantPool) { ConstantLookup lookup = constantLookups.get(id); if (lookup == null) { - ConstantMap pool = new ConstantMap(ObjectFactory.create(type, timeConverter), type.getName()); + ConstantMap pool = new ConstantMap(ObjectFactory.create(type, timeConverter), type); lookup = new ConstantLookup(pool, type); constantLookups.put(id, lookup); } @@ -140,7 +140,7 @@ final class ParserFactory { case "byte": return new ByteParser(); case "java.lang.String": - ConstantMap pool = new ConstantMap(ObjectFactory.create(type, timeConverter), type.getName()); + ConstantMap pool = new ConstantMap(ObjectFactory.create(type, timeConverter), type); ConstantLookup lookup = new ConstantLookup(pool, type); constantLookups.put(type.getId(), lookup); return new StringParser(lookup, event); @@ -304,34 +304,20 @@ final class ParserFactory { } @Override - public void skip(RecordingInput input) throws IOException { + public Object parseReferences(RecordingInput input) throws IOException { final int size = input.readInt(); + final Object[] array = new Object[size]; for (int i = 0; i < size; i++) { - elementParser.skip(input); - } - } - } - - private static final class CompositeParser extends Parser { - private final Parser[] parsers; - - public CompositeParser(Parser[] valueParsers) { - this.parsers = valueParsers; - } - - @Override - public Object parse(RecordingInput input) throws IOException { - final Object[] values = new Object[parsers.length]; - for (int i = 0; i < values.length; i++) { - values[i] = parsers[i].parse(input); + array[i] = elementParser.parse(input); } - return values; + return array; } @Override public void skip(RecordingInput input) throws IOException { - for (int i = 0; i < parsers.length; i++) { - parsers[i].skip(input); + final int size = input.readInt(); + for (int i = 0; i < size; i++) { + elementParser.skip(input); } } } @@ -340,6 +326,8 @@ final class ParserFactory { private final ConstantLookup lookup; private Object lastValue = 0; private long lastKey = -1; + private Object lastReferenceValue; + private long lastReferenceKey = -1; EventValueConstantParser(ConstantLookup lookup) { this.lookup = lookup; } @@ -359,6 +347,17 @@ final class ParserFactory { public void skip(RecordingInput input) throws IOException { input.readLong(); } + + @Override + public Object parseReferences(RecordingInput input) throws IOException { + long key = input.readLong(); + if (key == lastReferenceKey) { + return lastReferenceValue; + } + lastReferenceKey = key; + lastReferenceValue = new Reference(lookup.getLatestPool(), key); + return lastReferenceValue; + } } private static final class ConstantValueParser extends Parser { @@ -376,5 +375,10 @@ final class ParserFactory { public void skip(RecordingInput input) throws IOException { input.readLong(); } + + @Override + public Object parseReferences(RecordingInput input) throws IOException { + return new Reference(lookup.getLatestPool(), input.readLong()); + } } } diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/ParserFilter.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/ParserFilter.java index d805b934c932bf99e3273d0ea60e4c17d15d60ad..529823ec9be6cf3a99fd3732e4739647a143fe5b 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/ParserFilter.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/ParserFilter.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 @@ -29,7 +29,7 @@ import java.util.HashMap; import java.util.Map; import java.util.StringJoiner; -final class ParserFilter { +public final class ParserFilter { public static final ParserFilter ACCEPT_ALL = new ParserFilter(true, Map.of()); private final Map thresholds; diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/Reference.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/Reference.java new file mode 100644 index 0000000000000000000000000000000000000000..0426898a5ae3cc7cdbbf28a69f19a31d13bdbcd6 --- /dev/null +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/Reference.java @@ -0,0 +1,49 @@ +/* + * 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.jfr.internal.consumer; + +import jdk.jfr.internal.Type; + +/** + * A temporary placeholder, so objects can reference themselves (directly, or + * indirectly), when making a transition from numeric id references to Java + * object references. + */ +public record Reference(ConstantMap pool, long key) { + + Object resolve() { + return pool.get(key); + } + + public Type type() { + return pool.getType(); + } + + @Override + public String toString() { + return "ref: " + pool.getName() + "[" + key + "]"; + } +} \ No newline at end of file diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/StringParser.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/StringParser.java index 4cc8f4252aa35d2e769edd63702950c2a9b76780..1fd116beda128d746de4af75b7b1ad8e93400d91 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/StringParser.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/StringParser.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 @@ -220,4 +220,31 @@ public final class StringParser extends Parser { } throw new IOException("Unknown string encoding " + encoding); } + + @Override + public Object parseReferences(RecordingInput input) throws IOException { + byte encoding = input.readByte(); + if (Encoding.CONSTANT_POOL.is(encoding)) { + return new Reference(stringLookup.getLatestPool(), input.readLong()); + } + if (Encoding.EMPTY_STRING.is(encoding)) { + return null; + } + if (Encoding.NULL.is(encoding)) { + return null; + } + if (Encoding.CHAR_ARRAY.is(encoding)) { + charArrayParser.skip(input); + return null; + } + if (Encoding.UT8_BYTE_ARRAY.is(encoding)) { + utf8parser.skip(input); + return null; + } + if (Encoding.LATIN1_BYTE_ARRAY.is(encoding)) { + latin1parser.skip(input); + return null; + } + throw new IOException("Unknown string encoding " + encoding); + } } diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/filter/CheckpointEvent.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/filter/CheckpointEvent.java new file mode 100644 index 0000000000000000000000000000000000000000..72f40c0e7a722d33ff7998ffa7a268fdf2f1c7a4 --- /dev/null +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/filter/CheckpointEvent.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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.jfr.internal.consumer.filter; + +import java.util.Collection; +import java.util.LinkedHashMap; + +import jdk.jfr.internal.Type; + +/** + * Represents a checkpoint event. + *

+ * All positional values are relative to file start, not the chunk. + */ +public final class CheckpointEvent { + private final ChunkWriter chunkWriter; + private final LinkedHashMap pools = new LinkedHashMap<>(); + private final long startPosition; + + public CheckpointEvent(ChunkWriter chunkWriter, long startPosition) { + this.chunkWriter = chunkWriter; + this.startPosition = startPosition; + } + + public PoolEntry addEntry(Type type, long id, long startPosition, long endPosition, Object references) { + long typeId = type.getId(); + PoolEntry pe = new PoolEntry(startPosition, endPosition, type, id, references); + var cpp = pools.computeIfAbsent(typeId, k -> new CheckpointPool(typeId)); + cpp.add(pe); + chunkWriter.getPool(type).add(id, pe); + return pe; + } + + public long touchedPools() { + int count = 0; + for (CheckpointPool cpp : pools.values()) { + if (cpp.isTouched()) { + count++; + } + } + return count; + } + + public Collection getPools() { + return pools.values(); + } + + public long getStartPosition() { + return startPosition; + } + + public String toString() { + StringBuilder sb = new StringBuilder(); + for (CheckpointPool p : pools.values()) { + for (var e : p.getEntries()) { + if (e.isTouched()) { + sb.append(e.getType().getName() + " " + e.getId() + "\n"); + } + } + } + return sb.toString(); + } +} \ No newline at end of file diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/filter/CheckpointPool.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/filter/CheckpointPool.java new file mode 100644 index 0000000000000000000000000000000000000000..d4b1ce926be94d6f5636009488a242a33279b91a --- /dev/null +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/filter/CheckpointPool.java @@ -0,0 +1,70 @@ +/* + * 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. + */ +package jdk.jfr.internal.consumer.filter; + +import java.util.ArrayList; +import java.util.List; +/** + * Represents a constant pool in a checkpoint, both entries and type id + */ +final class CheckpointPool { + private final List entries = new ArrayList<>(); + private final long typeId; + + public CheckpointPool(long typeId) { + this.typeId = typeId; + } + + public boolean isTouched() { + for (var entry : entries) { + if (entry.isTouched()) { + return true; + } + } + return false; + } + + public long getTouchedCount() { + int count = 0; + for (var entry : entries) { + if (entry.isTouched()) { + count++; + } + } + return count; + } + + public void add(PoolEntry pe) { + entries.add(pe); + } + + public long getTypeId() { + return typeId; + } + + public List getEntries() { + return entries; + } +} \ No newline at end of file diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/filter/ChunkWriter.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/filter/ChunkWriter.java new file mode 100644 index 0000000000000000000000000000000000000000..8c22432512a1ad5a9c4daffce01e9fbec077e331 --- /dev/null +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/filter/ChunkWriter.java @@ -0,0 +1,239 @@ +/* + * 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. + */ +package jdk.jfr.internal.consumer.filter; + +import java.io.Closeable; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.ArrayDeque; +import java.util.Deque; +import java.util.function.Predicate; + +import jdk.jfr.consumer.RecordedEvent; +import jdk.jfr.internal.LongMap; +import jdk.jfr.internal.Type; +import jdk.jfr.internal.consumer.ChunkHeader; +import jdk.jfr.internal.consumer.FileAccess; +import jdk.jfr.internal.Logger; +import jdk.jfr.internal.LogLevel; +import jdk.jfr.internal.LogTag; +import jdk.jfr.internal.consumer.RecordingInput; +import jdk.jfr.internal.consumer.Reference; + +/** + * Class that can filter out events and associated constants from a recording + * file. + *

+ * All positional values are relative to file start, not the chunk. + */ +public final class ChunkWriter implements Closeable { + private LongMap pools = new LongMap<>(); + private final Deque checkpoints = new ArrayDeque<>(); + private final Path destination; + private final RecordingInput input; + private final RecordingOutput output; + private final Predicate filter; + + private long chunkStartPosition; + private boolean chunkComplete; + private long lastCheckpoint; + + public ChunkWriter(Path source, Path destination, Predicate filter) throws IOException { + this.destination = destination; + this.output = new RecordingOutput(destination.toFile()); + this.input = new RecordingInput(source.toFile(), FileAccess.UNPRIVILEGED); + this.filter = filter; + } + + Constants getPool(Type type) { + long typeId = type.getId(); + Constants pool = pools.get(typeId); + if (pool == null) { + pool = new Constants(type); + pools.put(typeId, pool); + } + return pool; + } + + public CheckpointEvent newCheckpointEvent(long startPosition) { + CheckpointEvent event = new CheckpointEvent(this, startPosition); + checkpoints.add(event); + return event; + } + + public boolean accept(RecordedEvent event) { + return filter.test(event); + } + + public void touch(Object object) { + if (object instanceof Object[] array) { + for (int i = 0; i < array.length; i++) { + touch(array[i]); + } + return; + } + if (object instanceof Reference ref) { + touchRef(ref); + } + } + + private void touchRef(Reference ref) { + Constants pool = pools.get(ref.type().getId()); + if (pool == null) { + String msg = "Can't resolve " + ref.type().getName() + "[" + ref.key() + "]"; + Logger.log(LogTag.JFR_SYSTEM_PARSER, LogLevel.DEBUG, msg); + return; + } + PoolEntry entry = pool.get(ref.key()); + if (entry != null && !entry.isTouched()) { + entry.touch(); + touch(entry.getReferences()); + } + } + public void writeEvent(long startPosition, long endPosition) throws IOException { + writeCheckpointEvents(startPosition); + write(startPosition, endPosition); + } + + // Write check point events before a position + private void writeCheckpointEvents(long before) throws IOException { + CheckpointEvent cp = checkpoints.peek(); + while (cp != null && cp.getStartPosition() < before) { + checkpoints.poll(); + long delta = 0; + if (lastCheckpoint != 0) { + delta = lastCheckpoint - output.position(); + } + lastCheckpoint = output.position(); + write(cp, delta); + cp = checkpoints.peek(); + } + } + + public void write(long startPosition, long endPosition) throws IOException { + if (endPosition < startPosition) { + throw new IOException("Start position must come before end position, start=" + startPosition + ", end=" + endPosition); + } + long backup = input.position(); + input.position(startPosition); + long n = endPosition - startPosition; + for (long i = 0; i < n; i++) { + output.writeByte(input.readByte()); + } + input.position(backup); + } + + @Override + public void close() throws IOException { + try { + output.close(); + } finally { + if (!chunkComplete) { + // Error occurred, clean up + if (Files.exists(destination)) { + Files.delete(destination); + } + } + } + } + + public void beginChunk(ChunkHeader header) throws IOException { + this.chunkComplete = false; + this.chunkStartPosition = output.position(); + input.position(header.getAbsoluteChunkStart()); + for (int i = 0; i < ChunkHeader.HEADER_SIZE; i++) { + output.writeByte(input.readByte()); + } + } + + public void endChunk(ChunkHeader header) throws IOException { + // write all outstanding checkpoints + writeCheckpointEvents(Long.MAX_VALUE); + long metadata = output.position(); + writeMetadataEvent(header); + updateHeader(output.position(), lastCheckpoint, metadata); + pools = new LongMap<>(); + chunkComplete = true; + lastCheckpoint = 0; + } + + private void writeMetadataEvent(ChunkHeader header) throws IOException { + long metadataposition = header.getMetadataPosition() + header.getAbsoluteChunkStart(); + input.position(metadataposition); + long size = input.readLong(); + input.position(metadataposition); + for (int i = 0; i < size; i++) { + output.writeByte(input.readByte()); + } + } + + private void write(CheckpointEvent event, long delta) throws IOException { + input.position(event.getStartPosition()); + long startPosition = output.position(); + + input.readLong(); // Read size + output.writePaddedUnsignedInt(0); // Size, 4 bytes reserved + output.writeLong(input.readLong()); // Constant pool id + output.writeLong(input.readLong()); // Start time + output.writeLong(input.readLong()); // Duration + input.readLong(); // Read delta + output.writeLong(delta); // Delta + output.writeByte(input.readByte()); // flush marker + + // Write even if touched pools are zero, checkpoint works as sync point + output.writeLong(event.touchedPools()); // Pool count + for (CheckpointPool pool : event.getPools()) { + if (pool.isTouched()) { + output.writeLong(pool.getTypeId()); + output.writeLong(pool.getTouchedCount()); + for (PoolEntry pe : pool.getEntries()) { + if (pe.isTouched()) { + write(pe.getStartPosition(), pe.getEndPosition()); // key + value + } + } + } + } + long endPosition = output.position(); + long size = endPosition - startPosition; + output.position(startPosition); + output.writePaddedUnsignedInt(size); + output.position(endPosition); + } + + private void updateHeader(long size, long constantPosition, long metadataPosition) throws IOException { + long backup = output.position(); + output.position(ChunkHeader.CHUNK_SIZE_POSITION + chunkStartPosition); + // Write chunk relative values + output.writeRawLong(size - chunkStartPosition); + output.writeRawLong(constantPosition - chunkStartPosition); + output.writeRawLong(metadataPosition - chunkStartPosition); + output.position(backup); + } + + public RecordingInput getInput() { + return input; + } +} \ No newline at end of file diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/filter/Constants.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/filter/Constants.java new file mode 100644 index 0000000000000000000000000000000000000000..c670aded874d7f53b663c88b253b5e7320c4a727 --- /dev/null +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/filter/Constants.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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package jdk.jfr.internal.consumer.filter; + +import jdk.jfr.internal.LongMap; +import jdk.jfr.internal.Type; + +/** + * Holds the chunk global state of constants + */ +final class Constants { + private final LongMap table = new LongMap<>(); + private final Type type; + + public Constants(Type type) { + this.type = type; + } + + public void add(long key, PoolEntry entry) { + table.put(key, entry); + } + + public PoolEntry get(long key) { + return table.get(key); + } + + public String toString() { + return "Pool: " + type.getName() + " size = " + table.size(); + } +} \ No newline at end of file diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/filter/PoolEntry.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/filter/PoolEntry.java new file mode 100644 index 0000000000000000000000000000000000000000..7e5d7745a1e4e56f6378549237275bd73aeeb6ca --- /dev/null +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/filter/PoolEntry.java @@ -0,0 +1,88 @@ +/* + * 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. + */ +package jdk.jfr.internal.consumer.filter; + +import jdk.jfr.internal.Type; + +/** + * Represents the binary content of constant pool, both key and value. + *

+ * All positional values are relative to file start, not the chunk. + */ +final class PoolEntry { + private final long startPosition; + private final long endPosition; + private final Type type; + private final long keyId; + private final Object references; + + private boolean touched; + + PoolEntry(long startPosition, long endPosition, Type type, long keyId, Object references) { + this.startPosition = startPosition; + this.endPosition = endPosition; + this.type = type; + this.keyId = keyId; + this.references = references; + } + + public void touch() { + this.touched = true; + } + + public boolean isTouched() { + return touched; + } + + public Object getReferences() { + return references; + } + + public long getStartPosition() { + return startPosition; + } + + public long getEndPosition() { + return endPosition; + } + + public Type getType() { + return type; + } + + public long getId() { + return keyId; + } + + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("start: ").append(startPosition).append("\n"); + sb.append("end: ").append(endPosition).append("\n"); + sb.append("type: ").append(type).append(" (").append(type.getId()).append(")\n"); + sb.append("key: ").append(keyId).append("\n"); + sb.append("object: ").append(references).append("\n"); + return sb.toString(); + } +} \ No newline at end of file diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/filter/RecordingOutput.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/filter/RecordingOutput.java new file mode 100644 index 0000000000000000000000000000000000000000..9aebb27238c5b90fcc6c88e0285387a8d5a305c6 --- /dev/null +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/filter/RecordingOutput.java @@ -0,0 +1,154 @@ +/* + * 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. + */ +package jdk.jfr.internal.consumer.filter; + +import java.io.Closeable; +import java.io.File; +import java.io.IOException; +import java.io.RandomAccessFile; + +/** + * Write cache and LEB128 encoder + */ +final class RecordingOutput implements Closeable { + private final RandomAccessFile file; + private final byte[] buffer = new byte[16384]; + private int bufferPosition; + private long position; + + public RecordingOutput(File file) throws IOException { + this.file = new RandomAccessFile(file, "rw"); + } + + public void writeByte(byte value) throws IOException { + if (!(bufferPosition < buffer.length)) { + flush(); + } + buffer[bufferPosition++] = value; + position++; + } + + public void writeRawLong(long v) throws IOException { + writeByte((byte) ((v >> 56) & 0xff)); + writeByte((byte) ((v >> 48) & 0xff)); + writeByte((byte) ((v >> 40) & 0xff)); + writeByte((byte) ((v >> 32) & 0xff)); + writeByte((byte) ((v >> 24) & 0xff)); + writeByte((byte) ((v >> 16) & 0xff)); + writeByte((byte) ((v >> 8) & 0xff)); + writeByte((byte) ((v) & 0xff)); + } + + public void writePaddedUnsignedInt(long value) throws IOException { + if (value < 0) { + throw new IOException("Padded value can't be negative"); + } + if (value >= 1 << 28) { + throw new IOException("Padded value must fit four bytes"); + } + byte b0 = (byte) (value | 0x80); + byte b1 = (byte) (value >> 7 | 0x80); + byte b2 = (byte) (value >> 14 | 0x80); + byte b3 = (byte) (value >> 21); + writeByte(b0); + writeByte(b1); + writeByte(b2); + writeByte(b3); + } + + // Essentially copied from EventWriter#putLong + public void writeLong(long v) throws IOException { + if ((v & ~0x7FL) == 0L) { + writeByte((byte) v); // 0-6 + return; + } + writeByte((byte) (v | 0x80L)); // 0-6 + v >>>= 7; + if ((v & ~0x7FL) == 0L) { + writeByte((byte) v); // 7-13 + return; + } + writeByte((byte) (v | 0x80L)); // 7-13 + v >>>= 7; + if ((v & ~0x7FL) == 0L) { + writeByte((byte) v); // 14-20 + return; + } + writeByte((byte) (v | 0x80L)); // 14-20 + v >>>= 7; + if ((v & ~0x7FL) == 0L) { + writeByte((byte) v); // 21-27 + return; + } + writeByte((byte) (v | 0x80L)); // 21-27 + v >>>= 7; + if ((v & ~0x7FL) == 0L) { + writeByte((byte) v); // 28-34 + return; + } + writeByte((byte) (v | 0x80L)); // 28-34 + v >>>= 7; + if ((v & ~0x7FL) == 0L) { + writeByte((byte) v); // 35-41 + return; + } + writeByte((byte) (v | 0x80L)); // 35-41 + v >>>= 7; + if ((v & ~0x7FL) == 0L) { + writeByte((byte) v); // 42-48 + return; + } + writeByte((byte) (v | 0x80L)); // 42-48 + v >>>= 7; + + if ((v & ~0x7FL) == 0L) { + writeByte((byte) v); // 49-55 + return; + } + writeByte((byte) (v | 0x80L)); // 49-55 + writeByte((byte) (v >>> 7)); // 56-63, last byte as is. + } + + public void position(long pos) throws IOException { + flush(); + position = pos; + file.seek(position); + } + + public long position() throws IOException { + return position; + } + + public void flush() throws IOException { + file.write(buffer, 0, bufferPosition); + bufferPosition = 0; + } + + @Override + public void close() throws IOException { + flush(); + file.close(); + } +} diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/instrument/SocketChannelImplInstrumentor.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/instrument/SocketChannelImplInstrumentor.java index 6d353112dff0d062e7b4169be646bf1ecb0fde19..a83fabfbaa82b4ecbeffe8ff094517b021c34904 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/instrument/SocketChannelImplInstrumentor.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/instrument/SocketChannelImplInstrumentor.java @@ -52,7 +52,7 @@ final class SocketChannelImplInstrumentor { int bytesRead = 0; long start = 0; try { - start = EventHandler.timestamp();; + start = EventHandler.timestamp(); bytesRead = read(dst); } finally { long duration = EventHandler.timestamp() - start; diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/tool/Command.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/tool/Command.java index 031dbd28da905f7816bc07a51196e969c7e636c3..fc3b46ced54bd97f19c2bb78ee3ba223516e175e 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/tool/Command.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/tool/Command.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 @@ -38,13 +38,7 @@ import java.nio.file.Paths; import java.util.ArrayList; import java.util.Collections; import java.util.Deque; -import java.util.HashMap; import java.util.List; -import java.util.Map; -import java.util.function.Function; -import java.util.function.Predicate; - -import jdk.jfr.EventType; abstract class Command { public static final String title = "Tool for working with Flight Recorder files"; @@ -56,6 +50,7 @@ abstract class Command { commands.add(new Print()); commands.add(new Configure()); commands.add(new Metadata()); + commands.add(new Scrub()); commands.add(new Summary()); commands.add(new Assemble()); commands.add(new Disassemble()); @@ -287,6 +282,10 @@ abstract class Command { displayOptionUsage(stream); } + protected static char quoteCharacter() { + return File.pathSeparatorChar == ';' ? '"' : '\''; + } + protected final void println() { System.out.println(); } @@ -299,6 +298,12 @@ abstract class Command { System.out.println(text); } + public static void checkCommonError(Deque options, String typo, String correct) throws UserSyntaxException { + if (typo.equals(options.peek())) { + throw new UserSyntaxException("unknown option " + typo + ", did you mean " + correct + "?"); + } + } + protected final boolean matches(String command) { for (String s : getNames()) { if (s.equals(command)) { @@ -319,107 +324,4 @@ abstract class Command { return names; } - public static void checkCommonError(Deque options, String typo, String correct) throws UserSyntaxException { - if (typo.equals(options.peek())) { - throw new UserSyntaxException("unknown option " + typo + ", did you mean " + correct + "?"); - } - } - - protected static final char quoteCharacter() { - return File.pathSeparatorChar == ';' ? '"' : '\''; - } - - private static Predicate recurseIfPossible(Predicate filter) { - return x -> filter != null && filter.test(x); - } - - private static String acronomify(String multipleWords) { - boolean newWord = true; - String acronym = ""; - for (char c : multipleWords.toCharArray()) { - if (newWord) { - if (Character.isAlphabetic(c) && Character.isUpperCase(c)) { - acronym += c; - } - } - newWord = Character.isWhitespace(c); - } - return acronym; - } - - private static boolean match(String text, String filter) { - if (filter.length() == 0) { - // empty filter string matches if string is empty - return text.length() == 0; - } - if (filter.charAt(0) == '*') { // recursive check - filter = filter.substring(1); - for (int n = 0; n <= text.length(); n++) { - if (match(text.substring(n), filter)) - return true; - } - } else if (text.length() == 0) { - // empty string and non-empty filter does not match - return false; - } else if (filter.charAt(0) == '?') { - // eat any char and move on - return match(text.substring(1), filter.substring(1)); - } else if (filter.charAt(0) == text.charAt(0)) { - // eat chars and move on - return match(text.substring(1), filter.substring(1)); - } - return false; - } - - private static List explodeFilter(String filter) throws UserSyntaxException { - List list = new ArrayList<>(); - for (String s : filter.split(",")) { - s = s.trim(); - if (!s.isEmpty()) { - list.add(s); - } - } - return list; - } - - protected static final Predicate addCategoryFilter(String filterText, Predicate eventFilter) throws UserSyntaxException { - List filters = explodeFilter(filterText); - Predicate newFilter = recurseIfPossible(eventType -> { - for (String category : eventType.getCategoryNames()) { - for (String filter : filters) { - if (match(category, filter)) { - return true; - } - if (category.contains(" ") && acronomify(category).equals(filter)) { - return true; - } - } - } - return false; - }); - return eventFilter == null ? newFilter : eventFilter.or(newFilter); - } - - protected static final Predicate addEventFilter(String filterText, final Predicate eventFilter) throws UserSyntaxException { - List filters = explodeFilter(filterText); - Predicate newFilter = recurseIfPossible(eventType -> { - for (String filter : filters) { - String fullEventName = eventType.getName(); - if (match(fullEventName, filter)) { - return true; - } - String eventName = fullEventName.substring(fullEventName.lastIndexOf(".") + 1); - if (match(eventName, filter)) { - return true; - } - } - return false; - }); - return eventFilter == null ? newFilter : eventFilter.or(newFilter); - } - - protected static final Predicate addCache(final Predicate filter, Function cacheFunction) { - Map cache = new HashMap<>(); - return t -> cache.computeIfAbsent(cacheFunction.apply(t), x -> filter.test(t)); - } } diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/tool/Filters.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/tool/Filters.java new file mode 100644 index 0000000000000000000000000000000000000000..cc567bf9a3a2d75d52ac057179dcb7fb08f6b035 --- /dev/null +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/tool/Filters.java @@ -0,0 +1,178 @@ +/* + * 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. + */ +package jdk.jfr.internal.tool; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.function.Function; +import java.util.function.Predicate; + +import jdk.jfr.EventType; +import jdk.jfr.consumer.RecordedThread; +import jdk.jfr.consumer.RecordedEvent; + +/** + * Helper class for creating filters. + */ +public class Filters { + private static final Predicate FALSE_THREAD_PREDICATE = e -> false; + + static Predicate createCategoryFilter(String filterText) throws UserSyntaxException { + List filters = explodeFilter(filterText); + Predicate f = eventType -> { + for (String category : eventType.getCategoryNames()) { + for (String filter : filters) { + if (match(category, filter)) { + return true; + } + if (category.contains(" ") && acronymify(category).equals(filter)) { + return true; + } + } + } + return false; + }; + return createCache(f, EventType::getId); + } + + static Predicate createEventTypeFilter(String filterText) throws UserSyntaxException { + List filters = explodeFilter(filterText); + Predicate f = eventType -> { + for (String filter : filters) { + String fullEventName = eventType.getName(); + if (match(fullEventName, filter)) { + return true; + } + String eventName = fullEventName.substring(fullEventName.lastIndexOf(".") + 1); + if (match(eventName, filter)) { + return true; + } + } + return false; + }; + return createCache(f, EventType::getId); + } + + public static Predicate matchAny(List> filters) { + if (filters.isEmpty()) { + return t -> true; + } + if (filters.size() == 1) { + return filters.get(0); + } + return t -> { + for (Predicate p : filters) { + if (!p.test(t)) { + return false; + } + } + return true; + }; + } + + static Predicate fromEventType(Predicate filter) { + return e -> filter.test(e.getEventType()); + } + + static Predicate fromRecordedThread(Predicate filter) { + Predicate cachePredicate = createCache(filter, RecordedThread::getId); + return event -> { + RecordedThread t = event.getThread(); + if (t == null || t.getJavaName() == null) { + return false; + } + return cachePredicate.test(t); + }; + } + + static Predicate createThreadFilter(String filterText) throws UserSyntaxException { + List filters = explodeFilter(filterText); + return thread -> { + String threadName = thread.getJavaName(); + for (String filter : filters) { + if (match(threadName, filter)) { + return true; + } + } + return false; + }; + } + + private static final Predicate createCache(final Predicate filter, Function cacheFunction) { + Map cache = new HashMap<>(); + return t -> cache.computeIfAbsent(cacheFunction.apply(t), x -> filter.test(t)); + } + + private static String acronymify(String multipleWords) { + boolean newWord = true; + String acronym = ""; + for (char c : multipleWords.toCharArray()) { + if (newWord) { + if (Character.isAlphabetic(c) && Character.isUpperCase(c)) { + acronym += c; + } + } + newWord = Character.isWhitespace(c); + } + return acronym; + } + + private static boolean match(String text, String filter) { + if (filter.length() == 0) { + // empty filter string matches if string is empty + return text.length() == 0; + } + if (filter.charAt(0) == '*') { // recursive check + filter = filter.substring(1); + for (int n = 0; n <= text.length(); n++) { + if (match(text.substring(n), filter)) + return true; + } + } else if (text.length() == 0) { + // empty string and non-empty filter does not match + return false; + } else if (filter.charAt(0) == '?') { + // eat any char and move on + return match(text.substring(1), filter.substring(1)); + } else if (filter.charAt(0) == text.charAt(0)) { + // eat chars and move on + return match(text.substring(1), filter.substring(1)); + } + return false; + } + + private static List explodeFilter(String filter) throws UserSyntaxException { + List list = new ArrayList<>(); + for (String s : filter.split(",")) { + s = s.trim(); + if (!s.isEmpty()) { + list.add(s); + } + } + return list; + } +} diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/tool/JSONWriter.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/tool/JSONWriter.java index cbf508306d54376127d3e75c20ec5414bc79d854..3be2dd6c19913fde55a36f40722538e07b64a9f2 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/tool/JSONWriter.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/tool/JSONWriter.java @@ -63,7 +63,7 @@ final class JSONWriter extends EventPrintWriter { @Override protected void printEnd() { - printArrayEnd();; + printArrayEnd(); printObjectEnd(); printObjectEnd(); } diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/tool/Main.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/tool/Main.java index 1629e4d28c85efaac2484be864ea815d88f054e6..36e6ea1c234aad380cf2c63f9ef6a167d04a43d5 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/tool/Main.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/tool/Main.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 @@ -66,7 +66,7 @@ public final class Main { System.out.println(); System.out.println(" jfr print --json --events CPULoad recording.jfr"); System.out.println(); - char q = Print.quoteCharacter(); + char q = Command.quoteCharacter(); System.out.println(" jfr print --categories " + q + "GC,JVM,Java*" + q + " recording.jfr"); System.out.println(); System.out.println(" jfr print --events " + q + "jdk.*" + q + " --stack-depth 64 recording.jfr"); diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/tool/Metadata.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/tool/Metadata.java index c27bf935a2a487fe6fc05744ee8945e787a6ce23..65e38f7326f22c5f7829bc0592c2255e448e73a4 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/tool/Metadata.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/tool/Metadata.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 @@ -163,6 +163,7 @@ final class Metadata extends Command { boolean showIds = false; boolean foundEventFilter = false; boolean foundCategoryFilter = false; + List> filters = new ArrayList<>(); Predicate filter = null; int optionCount = options.size(); while (optionCount > 0) { @@ -177,7 +178,7 @@ final class Metadata extends Command { foundEventFilter = true; String filterStr = options.remove(); warnForWildcardExpansion("--events", filterStr); - filter = addEventFilter(filterStr, filter); + filters.add(Filters.createEventTypeFilter(filterStr)); } if (acceptFilterOption(options, "--categories")) { if (foundCategoryFilter) { @@ -186,7 +187,7 @@ final class Metadata extends Command { foundCategoryFilter = true; String filterStr = options.remove(); warnForWildcardExpansion("--categories", filterStr); - filter = addCategoryFilter(filterStr, filter); + filters.add(Filters.createCategoryFilter(filterStr)); } if (optionCount == options.size()) { // No progress made @@ -200,8 +201,8 @@ final class Metadata extends Command { try (PrintWriter pw = new PrintWriter(System.out, false, UTF_8)) { PrettyWriter prettyWriter = new PrettyWriter(pw); prettyWriter.setShowIds(showIds); - if (filter != null) { - filter = addCache(filter, type -> type.getId()); + if (!filters.isEmpty()) { + filter = Filters.matchAny(filters); } List types = findTypes(file); diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/tool/Print.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/tool/Print.java index 991ac554f4c0e23ada3c3ab13c578b279fdcc06b..2fc33a90cd9754176443afef7f04c7fc3cee3dbc 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/tool/Print.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/tool/Print.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 @@ -102,7 +102,7 @@ final class Print extends Command { public void execute(Deque options) throws UserSyntaxException, UserDataException { Path file = getJFRInputFile(options); PrintWriter pw = new PrintWriter(System.out, false, UTF_8); - Predicate eventFilter = null; + List> eventFilters = new ArrayList<>(); int stackDepth = 5; EventPrintWriter eventWriter = null; int optionCount = options.size(); @@ -116,7 +116,7 @@ final class Print extends Command { foundEventFilter = true; String filter = options.remove(); warnForWildcardExpansion("--events", filter); - eventFilter = addEventFilter(filter, eventFilter); + eventFilters.add(Filters.createEventTypeFilter(filter)); } if (acceptFilterOption(options, "--categories")) { if (foundCategoryFilter) { @@ -125,7 +125,7 @@ final class Print extends Command { foundCategoryFilter = true; String filter = options.remove(); warnForWildcardExpansion("--categories", filter); - eventFilter = addCategoryFilter(filter, eventFilter); + eventFilters.add(Filters.createCategoryFilter(filter)); } if (acceptOption(options, "--stack-depth")) { String value = options.pop(); @@ -156,9 +156,8 @@ final class Print extends Command { eventWriter = new PrettyWriter(pw); // default to pretty printer } eventWriter.setStackDepth(stackDepth); - if (eventFilter != null) { - eventFilter = addCache(eventFilter, eventType -> eventType.getId()); - eventWriter.setEventFilter(eventFilter); + if (!eventFilters.isEmpty()) { + eventWriter.setEventFilter(Filters.matchAny(eventFilters)); } try { eventWriter.print(file); diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/tool/Scrub.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/tool/Scrub.java new file mode 100644 index 0000000000000000000000000000000000000000..f553e4e8144ac9b759ef158a77eedcbb5374e2ef --- /dev/null +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/tool/Scrub.java @@ -0,0 +1,194 @@ +/* + * 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. + */ + +package jdk.jfr.internal.tool; + +import java.io.IOException; +import java.io.PrintStream; +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.Deque; +import java.util.List; +import java.util.function.Predicate; + +import jdk.jfr.consumer.RecordedEvent; +import jdk.jfr.consumer.RecordingFile; + +final class Scrub extends Command { + + @Override + public String getName() { + return "scrub"; + } + + @Override + public List getOptionSyntax() { + List list = new ArrayList<>(); + list.add("[--include-events ]"); + list.add("[--exclude-events ]"); + list.add("[--include-categories ]"); + list.add("[--exclude-categories ]"); + list.add("[--include-threads ]"); + list.add("[--exclude-threads ]"); + list.add(""); + list.add("[]"); + return list; + } + + @Override + protected String getTitle() { + return "Scrub contents of a recording file"; + } + + @Override + public String getDescription() { + return getTitle() + ". See 'jfr help scrub' for details."; + } + + @Override + public void displayOptionUsage(PrintStream stream) { + // 01234567890123456789012345678901234567890123467890123456789012345678901234567890 + stream.println(" --include-events Select events matching an event name"); + stream.println(); + stream.println(" --exclude-events Exclude events matching an event name"); + stream.println(); + stream.println(" --include-categories Select events matching a category name"); + stream.println(); + stream.println(" --exclude-categories Exclude events matching a category name"); + stream.println(); + stream.println(" --include-threads Select events matching a thread name"); + stream.println(); + stream.println(" --exclude-threads Exclude events matching a thread name"); + stream.println(); + stream.println(" The input file to read events from"); + stream.println(); + stream.println(" The output file to write filter events to. "); + stream.println(" If no file is specified, it will be written to"); + stream.println(" the same path as the input file, but with"); + stream.println(" \"-scrubbed\" appended to the filename"); + stream.println(); + stream.println(" The filter is a comma-separated list of names, simple and/or qualified,"); + stream.println(" and/or quoted glob patterns. If multiple filters are used, they "); + stream.println(" are applied in the specified order"); + stream.println(); + stream.println("Example usage:"); + stream.println(); + stream.println(" jfr scrub --include-events 'jdk.Socket*' recording.jfr socket-only.jfr"); + stream.println(); + stream.println(" jfr scrub --exclude-events InitialEnvironmentVariable recording.jfr no-psw.jfr"); + stream.println(); + stream.println(" jfr scrub --include-threads main recording.jfr"); + stream.println(); + stream.println(" jfr scrub --exclude-threads 'Foo*' recording.jfr"); + stream.println(); + stream.println(" jfr scrub --include-categories 'My App' recording.jfr"); + stream.println(); + stream.println(" jfr scrub --exclude-categories JVM,OS recording.jfr"); + } + + @Override + public void execute(Deque options) throws UserSyntaxException, UserDataException { + ensureMinArgumentCount(options, 1); + + Path last = Path.of(options.pollLast()); + ensureFileExtension(last, ".jfr"); + Path output = null; + Path input = null; + String peek = options.peekLast(); + if (peek != null && peek.endsWith(".jfr")) { + // Both source and destination specified + input = Path.of(options.pollLast()); + output = last; + } else { + // Only source file specified + Path file = last.getFileName(); + Path dir = last.getParent(); + String filename = file.toString(); + int index = filename.lastIndexOf("."); + String s = filename.substring(0, index); + String t = s + "-scrubbed.jfr"; + input = last; + output = dir == null ? Path.of(t) : dir.resolve(t); + } + ensureFileDoesNotExist(output); + + List> filters = new ArrayList<>(); + int optionCount = options.size(); + while (optionCount > 0) { + if (acceptFilterOption(options, "--include-events")) { + String filter = options.remove(); + warnForWildcardExpansion("--include-events", filter); + var f = Filters.createEventTypeFilter(filter); + filters.add(Filters.fromEventType(f)); + } + if (acceptFilterOption(options, "--exclude-events")) { + String filter = options.remove(); + warnForWildcardExpansion("--exclude-events", filter); + var f = Filters.createEventTypeFilter(filter); + filters.add(Filters.fromEventType(f.negate())); + } + if (acceptFilterOption(options, "--include-categories")) { + String filter = options.remove(); + warnForWildcardExpansion("--include-categories", filter); + var f = Filters.createCategoryFilter(filter); + filters.add(Filters.fromEventType(f)); + } + if (acceptFilterOption(options, "--exclude-categories")) { + String filter = options.remove(); + warnForWildcardExpansion("--exclude-categories", filter); + var f = Filters.createCategoryFilter(filter); + filters.add(Filters.fromEventType(f.negate())); + } + if (acceptFilterOption(options, "--include-threads")) { + String filter = options.remove(); + warnForWildcardExpansion("--include-threads", filter); + var f = Filters.createThreadFilter(filter); + filters.add(Filters.fromRecordedThread(f)); + } + if (acceptFilterOption(options, "--exclude-threads")) { + String filter = options.remove(); + warnForWildcardExpansion("--exclude-threads", filter); + var f = Filters.createThreadFilter(filter); + filters.add(Filters.fromRecordedThread(f).negate()); + } + if (optionCount == options.size()) { + // No progress made + checkCommonError(options, "--include-event", "--include-events"); + checkCommonError(options, "--include-category", "--include-categories"); + checkCommonError(options, "--include-thread", "--include-threads"); + throw new UserSyntaxException("unknown option " + options.peek()); + } + optionCount = options.size(); + } + + try (RecordingFile rf = new RecordingFile(input)) { + rf.write(output, Filters.matchAny(filters)); + } catch (IOException ioe) { + couldNotReadError(input, ioe); + } + println("Scrubbed recording file written to:"); + println(output.toAbsolutePath().toString()); + } +} diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/tool/Summary.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/tool/Summary.java index 767ccf63507857404f7407418589ff6fa00a8dd6..850e995acf37a608eaf5d58150259bd5a4928773 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/tool/Summary.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/tool/Summary.java @@ -100,7 +100,7 @@ final class Summary extends Command { } HashMap stats = new HashMap<>(); stats.put(0L, new Statistics(eventPrefix + "Metadata")); - stats.put(1L, new Statistics(eventPrefix + "CheckPoint")); + stats.put(1L, new Statistics(eventPrefix + "Checkpoint")); int minWidth = 0; while (true) { long chunkEnd = ch.getEnd(); diff --git a/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/resources/MacResources.properties b/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/resources/MacResources.properties index 23a4f9d0437cb7b658ec48a98d851e99c20a1dd0..25a9facea5f2d1e2916e622efb80968c4c9a1a6f 100644 --- a/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/resources/MacResources.properties +++ b/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/resources/MacResources.properties @@ -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 @@ -80,7 +80,7 @@ message.building-dmg=Building DMG package for {0}. message.running-script=Running shell script on application image [{0}]. message.preparing-dmg-setup=Preparing dmg setup: {0}. message.creating-dmg-file=Creating DMG file: {0}. -message.dmg-cannot-be-overwritten=Dmg file exists ({0} and can not be removed. +message.dmg-cannot-be-overwritten=Dmg file exists [{0}] and can not be removed. message.output-to-location=Result DMG installer for {0}: {1}. message.building-pkg=Building PKG package for {0}. message.preparing-scripts=Preparing package scripts. diff --git a/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/resources/MacResources_ja.properties b/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/resources/MacResources_ja.properties index d9da226ec9229c948e3d46bbd15115e159ac4bf5..291130fb23737ee9ac9db6c0d260f41fe617da54 100644 --- a/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/resources/MacResources_ja.properties +++ b/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/resources/MacResources_ja.properties @@ -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 @@ -79,7 +79,7 @@ message.building-dmg={0}\u306EDMG\u30D1\u30C3\u30B1\u30FC\u30B8\u3092\u4F5C\u621 message.running-script=\u30A2\u30D7\u30EA\u30B1\u30FC\u30B7\u30E7\u30F3\u30FB\u30A4\u30E1\u30FC\u30B8[{0}]\u3067\u30B7\u30A7\u30EB\u30FB\u30B9\u30AF\u30EA\u30D7\u30C8\u3092\u5B9F\u884C\u3057\u3066\u3044\u307E\u3059\u3002 message.preparing-dmg-setup=dmg\u306E\u8A2D\u5B9A\u3092\u6E96\u5099\u3057\u3066\u3044\u307E\u3059: {0} message.creating-dmg-file=DMG\u30D5\u30A1\u30A4\u30EB\u3092\u4F5C\u6210\u3057\u3066\u3044\u307E\u3059: {0} -message.dmg-cannot-be-overwritten=Dmg\u30D5\u30A1\u30A4\u30EB\u306F\u5B58\u5728\u3057({0}\u3001\u524A\u9664\u3067\u304D\u307E\u305B\u3093\u3002 +message.dmg-cannot-be-overwritten=Dmg\u30D5\u30A1\u30A4\u30EB\u306F\u5B58\u5728\u3057[{0}]\u3001\u524A\u9664\u3067\u304D\u307E\u305B\u3093\u3002 message.output-to-location={0}\u306E\u7D50\u679C\u306EDMG\u30A4\u30F3\u30B9\u30C8\u30FC\u30E9: {1} message.building-pkg={0}\u306EPKG\u30D1\u30C3\u30B1\u30FC\u30B8\u3092\u4F5C\u6210\u3057\u3066\u3044\u307E\u3059 message.preparing-scripts=\u30D1\u30C3\u30B1\u30FC\u30B8\u30FB\u30B9\u30AF\u30EA\u30D7\u30C8\u3092\u6E96\u5099\u3057\u3066\u3044\u307E\u3059 diff --git a/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/resources/MacResources_zh_CN.properties b/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/resources/MacResources_zh_CN.properties index d6f47a7bc85e7641da6253ba695ba2b5ab2a37fc..ecf9e8796d52114881bad9faf4f5baa64d7871d7 100644 --- a/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/resources/MacResources_zh_CN.properties +++ b/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/resources/MacResources_zh_CN.properties @@ -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 @@ -79,7 +79,7 @@ message.building-dmg=\u6B63\u5728\u4E3A {0} \u6784\u5EFA DMG \u7A0B\u5E8F\u5305\ message.running-script=\u6B63\u5728\u5E94\u7528\u7A0B\u5E8F\u6620\u50CF [{0}] \u4E0A\u8FD0\u884C shell \u811A\u672C\u3002 message.preparing-dmg-setup=\u6B63\u5728\u51C6\u5907 dmg \u8BBE\u7F6E: {0}\u3002 message.creating-dmg-file=\u6B63\u5728\u521B\u5EFA DMG \u6587\u4EF6: {0}\u3002 -message.dmg-cannot-be-overwritten=Dmg \u6587\u4EF6\u5DF2\u5B58\u5728 ({0}) \u4E14\u65E0\u6CD5\u5220\u9664\u3002 +message.dmg-cannot-be-overwritten=Dmg \u6587\u4EF6\u5DF2\u5B58\u5728 [{0}] \u4E14\u65E0\u6CD5\u5220\u9664\u3002 message.output-to-location=\u4E3A {0} \u751F\u6210\u7684 DMG \u5B89\u88C5\u7A0B\u5E8F: {1}\u3002 message.building-pkg=\u6B63\u5728\u4E3A {0} \u6784\u5EFA PKG \u7A0B\u5E8F\u5305\u3002 message.preparing-scripts=\u6B63\u5728\u51C6\u5907\u7A0B\u5E8F\u5305\u811A\u672C\u3002 diff --git a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/AddLauncherArguments.java b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/AddLauncherArguments.java index 84eb9197a2b89be6fd3eac285086f206085bc1d8..59268992602dd9d6ff3821affdc83aa5b9a71679 100644 --- a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/AddLauncherArguments.java +++ b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/AddLauncherArguments.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 @@ -54,6 +54,7 @@ import static jdk.jpackage.internal.StandardBundlerParam.SHORTCUT_HINT; * The add-launcher properties file may have any of: * * appVersion + * description * module * main-jar * main-class @@ -111,6 +112,9 @@ class AddLauncherArguments { Arguments.putUnlessNull(bundleParams, CLIOptions.VERSION.getId(), getOptionValue(CLIOptions.VERSION)); + Arguments.putUnlessNull(bundleParams, CLIOptions.DESCRIPTION.getId(), + getOptionValue(CLIOptions.DESCRIPTION)); + Arguments.putUnlessNull(bundleParams, CLIOptions.RELEASE.getId(), getOptionValue(CLIOptions.RELEASE)); diff --git a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/resources/HelpResources.properties b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/resources/HelpResources.properties index 27f0a491c2a22a1bd632e8fa747fdad1944a8145..658cb603cff690075bb127cc4535c899413c2d37 100644 --- a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/resources/HelpResources.properties +++ b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/resources/HelpResources.properties @@ -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 @@ -138,7 +138,7 @@ Generic Options:\n\ \ Name of launcher, and a path to a Properties file that contains\n\ \ a list of key, value pairs\n\ \ (absolute path or relative to the current directory)\n\ -\ The keys "module", "main-jar", "main-class",\n\ +\ The keys "module", "main-jar", "main-class", "description",\n\ \ "arguments", "java-options", "app-version", "icon",\n\ \ "win-console", "win-shortcut", "win-menu",\n\ \ "linux-app-category", and "linux-shortcut" can be used.\n\ diff --git a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/resources/HelpResources_ja.properties b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/resources/HelpResources_ja.properties index b241ab8403dc6309a7238e2a9d2cfd661e22b698..6ed6c2c90a9a857e801966aeeb209ab6fd18eeed 100644 --- a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/resources/HelpResources_ja.properties +++ b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/resources/HelpResources_ja.properties @@ -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 @@ -138,7 +138,7 @@ Generic Options:\n\ \ Name of launcher, and a path to a Properties file that contains\n\ \ a list of key, value pairs\n\ \ (absolute path or relative to the current directory)\n\ -\ The keys "module", "main-jar", "main-class",\n\ +\ The keys "module", "main-jar", "main-class", "description",\n\ \ "arguments", "java-options", "app-version", "icon",\n\ \ "win-console", "win-shortcut", "win-menu",\n\ \ "linux-app-category", and "linux-shortcut" can be used.\n\ diff --git a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/resources/HelpResources_zh_CN.properties b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/resources/HelpResources_zh_CN.properties index 09de3241d1b66ab94f01c3fd6a81140f6728c489..73a3db560edf62bac28f9c455a923371862f4672 100644 --- a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/resources/HelpResources_zh_CN.properties +++ b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/resources/HelpResources_zh_CN.properties @@ -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 @@ -138,7 +138,7 @@ Generic Options:\n\ \ Name of launcher, and a path to a Properties file that contains\n\ \ a list of key, value pairs\n\ \ (absolute path or relative to the current directory)\n\ -\ The keys "module", "main-jar", "main-class",\n\ +\ The keys "module", "main-jar", "main-class", "description",\n\ \ "arguments", "java-options", "app-version", "icon",\n\ \ "win-console", "win-shortcut", "win-menu",\n\ \ "linux-app-category", and "linux-shortcut" can be used.\n\ diff --git a/src/jdk.jpackage/windows/native/libwixhelper/libwixhelper.cpp b/src/jdk.jpackage/windows/native/libwixhelper/libwixhelper.cpp index 85e0229bc212f6708b7ca87f4262cdbc819a820a..6588ff05bbc410d0c34bb5cbf1badaf14e26b845 100644 --- a/src/jdk.jpackage/windows/native/libwixhelper/libwixhelper.cpp +++ b/src/jdk.jpackage/windows/native/libwixhelper/libwixhelper.cpp @@ -59,7 +59,7 @@ extern "C" { DWORD cchSize = 0; UINT result = MsiGetProperty(hInstall, TEXT("INSTALLDIR"), - TEXT(""), &cchSize); + (LPTSTR)TEXT(""), &cchSize); if (result == ERROR_MORE_DATA) { cchSize = cchSize + 1; // NULL termination szValue = new TCHAR[cchSize]; diff --git a/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/Selector.java b/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/Selector.java index 9d5408471487e99aa3811848ec719f2098136c35..aec5116bb2e03ef77731ad390b2825c7cdf1d620 100644 --- a/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/Selector.java +++ b/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/Selector.java @@ -302,7 +302,7 @@ class Selector { & SelectorInstanceWithDoc> SelectorKind(Class k) { - this.all = EnumSet.allOf(FormatCase.class);; + this.all = EnumSet.allOf(FormatCase.class); this.k = k; } } diff --git a/src/jdk.management.agent/share/classes/jdk/internal/agent/Agent.java b/src/jdk.management.agent/share/classes/jdk/internal/agent/Agent.java index 2d261bfb3a74b0433995752faf27639720ae3444..175c736e420c795daa088766ff74fc2a68864aec 100644 --- a/src/jdk.management.agent/share/classes/jdk/internal/agent/Agent.java +++ b/src/jdk.management.agent/share/classes/jdk/internal/agent/Agent.java @@ -51,7 +51,6 @@ import javax.management.remote.JMXConnectorServer; import javax.management.remote.JMXServiceURL; import static jdk.internal.agent.AgentConfigurationError.*; -import jdk.internal.agent.spi.AgentProvider; import jdk.internal.vm.VMSupport; import sun.management.jdp.JdpController; import sun.management.jdp.JdpException; diff --git a/src/jdk.management.agent/share/classes/jdk/internal/agent/spi/AgentProvider.java b/src/jdk.management.agent/share/classes/jdk/internal/agent/spi/AgentProvider.java deleted file mode 100644 index ea42d5974862d487509a0a7d6e2fda1f4b688cab..0000000000000000000000000000000000000000 --- a/src/jdk.management.agent/share/classes/jdk/internal/agent/spi/AgentProvider.java +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Copyright (c) 2016, 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. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package jdk.internal.agent.spi; - -import java.util.Properties; - -/** - * Service interface for management agent - */ -public abstract class AgentProvider { - - /** - * Instantiates a new AgentProvider. - * - * @throws SecurityException if the subclass (and calling code) does not - * have - * {@code RuntimePermission("sun.management.spi.AgentProvider.subclass")} - */ - protected AgentProvider() { - this(checkSubclassPermission()); - } - - private AgentProvider(Void unused) { - } - - private static Void checkSubclassPermission() { - @SuppressWarnings("removal") - SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - sm.checkPermission(new RuntimePermission(AgentProvider.class.getName() + ".subclass")); - } - return null; - } - - /** - * Gets the name of the agent provider. - * - * @return name of agent provider - */ - public abstract String getName(); - - /** - * Initializes and starts the agent. - * - * @throws IllegalStateException if this agent has already been started. - */ - public abstract void startAgent(); - - /** - * Initializes and starts the agent at given port and with given properties - * - * @param props environment variables for agent - * - * @throws IllegalStateException if this agent has already been started. - */ - public abstract void startAgent(Properties props); - - /** - * Checks if agent is started and not terminated. - * - * @return true if agent is running, false otherwise. - */ - public abstract boolean isActive(); - - /** - * Stops this agent. - * - * @throws IllegalStateException if this agent is not started. - */ - public abstract void stopAgent(); -} diff --git a/src/jdk.management.agent/share/classes/module-info.java b/src/jdk.management.agent/share/classes/module-info.java index 921744822b61197d23c6f0438df741d7f0fccaac..9688e22b9f9740eb4b3df2e38381a03edfc156cb 100644 --- a/src/jdk.management.agent/share/classes/module-info.java +++ b/src/jdk.management.agent/share/classes/module-info.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 @@ -39,6 +39,4 @@ module jdk.management.agent { requires java.management.rmi; exports jdk.internal.agent to jdk.jconsole; - - uses jdk.internal.agent.spi.AgentProvider; } diff --git a/src/jdk.management.jfr/share/classes/jdk/management/jfr/DiskRepository.java b/src/jdk.management.jfr/share/classes/jdk/management/jfr/DiskRepository.java index 7ce5f9c93602e0b7e3a637018c847c42a33371be..d8ff2debe9ef92b550edebb9d3d046fbeadd8d66 100644 --- a/src/jdk.management.jfr/share/classes/jdk/management/jfr/DiskRepository.java +++ b/src/jdk.management.jfr/share/classes/jdk/management/jfr/DiskRepository.java @@ -179,7 +179,7 @@ final class DiskRepository implements Closeable { bufferIndex = 0; break; case CHECKPOINT_EVENT_HEADER_BYTE_ARRAY_CONTENT: - processCheckPointHeader(); + processCheckpointHeader(); break; case CHECKPOINT_EVENT_FLUSH_TYPE: processFlush(); @@ -286,10 +286,10 @@ final class DiskRepository implements Closeable { } } - private void processCheckPointHeader() throws IOException { + private void processCheckpointHeader() throws IOException { buffer.put(bufferIndex, nextByte(true)); if (bufferIndex == HEADER_SIZE) { - writeCheckPointHeader(); + writeCheckpointHeader(); state = State.EVENT_PAYLOAD; bufferIndex = 0; } @@ -321,7 +321,7 @@ final class DiskRepository implements Closeable { } } - private void writeCheckPointHeader() throws IOException { + private void writeCheckpointHeader() throws IOException { Objects.requireNonNull(raf); byte state = buffer.get(HEADER_FILE_STATE_POSITION); boolean complete = state == COMPLETE_STATE; diff --git a/src/jdk.management.jfr/share/classes/jdk/management/jfr/FlightRecorderMXBeanImpl.java b/src/jdk.management.jfr/share/classes/jdk/management/jfr/FlightRecorderMXBeanImpl.java index be71c5113b849c0180d17be469eeec56194e7434..11afb8310cab9b918e5ab1353ea685f51d76183e 100644 --- a/src/jdk.management.jfr/share/classes/jdk/management/jfr/FlightRecorderMXBeanImpl.java +++ b/src/jdk.management.jfr/share/classes/jdk/management/jfr/FlightRecorderMXBeanImpl.java @@ -215,10 +215,10 @@ final class FlightRecorderMXBeanImpl extends StandardEmitterMBean implements Fli } @Override - public void setRecordingSettings(long recording, Map values) throws IllegalArgumentException { - Objects.requireNonNull(values); + public void setRecordingSettings(long recording, Map settings) throws IllegalArgumentException { + Objects.requireNonNull(settings, "settings"); MBeanUtils.checkControl(); - getExistingRecording(recording).setSettings(values); + getExistingRecording(recording).setSettings(settings); } @SuppressWarnings("removal") @@ -241,11 +241,11 @@ final class FlightRecorderMXBeanImpl extends StandardEmitterMBean implements Fli } @Override - public void setConfiguration(long recording, String configuration) throws IllegalArgumentException { - Objects.requireNonNull(configuration); + public void setConfiguration(long recording, String contents) throws IllegalArgumentException { + Objects.requireNonNull(contents, "contents"); MBeanUtils.checkControl(); try { - Configuration c = Configuration.create(new StringReader(configuration)); + Configuration c = Configuration.create(new StringReader(contents)); getExistingRecording(recording).setSettings(c.getSettings()); } catch (IOException | ParseException e) { throw new IllegalArgumentException("Could not parse configuration", e); @@ -254,7 +254,7 @@ final class FlightRecorderMXBeanImpl extends StandardEmitterMBean implements Fli @Override public void setPredefinedConfiguration(long recording, String configurationName) throws IllegalArgumentException { - Objects.requireNonNull(configurationName); + Objects.requireNonNull(configurationName, "configurationName"); MBeanUtils.checkControl(); Recording r = getExistingRecording(recording); for (Configuration c : Configuration.getConfigurations()) { @@ -267,15 +267,15 @@ final class FlightRecorderMXBeanImpl extends StandardEmitterMBean implements Fli } @Override - public void copyTo(long recording, String path) throws IOException { - Objects.requireNonNull(path); + public void copyTo(long recording, String outputFile) throws IOException { + Objects.requireNonNull(outputFile, "outputFile"); MBeanUtils.checkControl(); - getExistingRecording(recording).dump(Paths.get(path)); + getExistingRecording(recording).dump(Paths.get(outputFile)); } @Override public void setRecordingOptions(long recording, Map options) throws IllegalArgumentException { - Objects.requireNonNull(options); + Objects.requireNonNull(options, "options"); MBeanUtils.checkControl(); // Make local copy to prevent concurrent modification Map ops = new HashMap(options); diff --git a/src/jdk.random/share/classes/jdk/random/L32X64MixRandom.java b/src/jdk.random/share/classes/jdk/random/L32X64MixRandom.java index 1cb222e9cca93db7e9df4445357110c0857abeb2..1b64a4b28cd9292c07faf74e10f2421b158f15e4 100644 --- a/src/jdk.random/share/classes/jdk/random/L32X64MixRandom.java +++ b/src/jdk.random/share/classes/jdk/random/L32X64MixRandom.java @@ -155,6 +155,8 @@ public final class L32X64MixRandom extends AbstractSplittableWithBrineGenerator // Force a to be odd. this.a = a | 1; this.s = s; + this.x0 = x0; + this.x1 = x1; // If x0 and x1 are both zero, we must choose nonzero values. if ((x0 | x1) == 0) { int v = s; diff --git a/src/utils/IdealGraphVisualizer/Bytecodes/pom.xml b/src/utils/IdealGraphVisualizer/Bytecodes/pom.xml index 188537f81d6efdf3605da92463fffd2fcaf0d8d4..e87ad7fb5099876d51ff073cab63cb6bd62953a1 100644 --- a/src/utils/IdealGraphVisualizer/Bytecodes/pom.xml +++ b/src/utils/IdealGraphVisualizer/Bytecodes/pom.xml @@ -1,6 +1,6 @@ diff --git a/src/utils/IdealGraphVisualizer/application/src/main/resources/idealgraphvisualizer.conf b/src/utils/IdealGraphVisualizer/application/src/main/resources/idealgraphvisualizer.conf new file mode 100644 index 0000000000000000000000000000000000000000..500ed32f280aaec3c6faf6d61716e4007195551c --- /dev/null +++ b/src/utils/IdealGraphVisualizer/application/src/main/resources/idealgraphvisualizer.conf @@ -0,0 +1,24 @@ +# 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. + +# Open/export modules still accessed by the NetBeans Platform. +# All options must be passed in a single line for multi-platform support. +default_options="-J--add-opens=java.base/java.net=ALL-UNNAMED -J--add-opens=java.desktop/javax.swing.plaf.synth=ALL-UNNAMED -J--add-opens=java.desktop/com.sun.java.swing.plaf.gtk=ALL-UNNAMED -J--add-opens=java.desktop/javax.swing=ALL-UNNAMED -J--add-exports=java.desktop/sun.awt=ALL-UNNAMED" \ No newline at end of file diff --git a/src/utils/IdealGraphVisualizer/branding/pom.xml b/src/utils/IdealGraphVisualizer/branding/pom.xml index 67821ff46216ec7334cf240a681f6a11b0cb7221..ed33298d3e4c522d30f472a0b33e37e2ecf87265 100644 --- a/src/utils/IdealGraphVisualizer/branding/pom.xml +++ b/src/utils/IdealGraphVisualizer/branding/pom.xml @@ -1,6 +1,6 @@ "; - - private static final boolean PRINT_IR_ENCODING = Boolean.parseBoolean(System.getProperty("PrintIREncoding", "false")); - private static final Pattern IR_ENCODING_PATTERN = - Pattern.compile("(?<=" + IREncodingPrinter.START + "\r?\n)[\\s\\S]*(?=" + IREncodingPrinter.END + ")"); - private static final Pattern COMPILE_ID_PATTERN = Pattern.compile("compile_id='(\\d+)'"); - - private final Map compilations; - private final Class testClass; - private final Map> fails; - private final Pattern compileIdPatternForTestClass; - private final String hotspotPidFileName; - private IRMethod irMethod; // Current IR method to which rules are applied - private Method method; // Current method to which rules are applied - private IR irAnno; // Current IR annotation that is processed. - private int irRuleIndex; // Current IR rule index; - - public IRMatcher(String hotspotPidFileName, String irEncoding, Class testClass) { - this.compilations = new HashMap<>(); - this.fails = new HashMap<>(); - this.testClass = testClass; - this.compileIdPatternForTestClass = Pattern.compile("compile_id='(\\d+)'.*" + Pattern.quote(testClass.getCanonicalName()) - + " (\\S+)"); - this.hotspotPidFileName = hotspotPidFileName; - setupTestMethods(irEncoding); - if (TestFramework.VERBOSE || PRINT_IR_ENCODING) { - System.out.println("Read IR encoding from test VM:"); - System.out.println(irEncoding); - } - if (!compilations.isEmpty()) { - parseHotspotPidFile(); - applyRules(); - } - } - - /** - * Sets up a map testname -> IRMethod (containing the PrintIdeal and PrintOptoAssembly output for testname). - */ - private void setupTestMethods(String irEncoding) { - Map irRulesMap = parseIREncoding(irEncoding); - for (Method m : testClass.getDeclaredMethods()) { - method = m; - IR[] irAnnos = m.getAnnotationsByType(IR.class); - if (irAnnos.length > 0) { - // Validation of legal @IR attributes and placement of the annotation was already done in Test VM. - int[] ids = irRulesMap.get(m.getName()); - TestFramework.check(ids != null, "Should find method name in validIrRulesMap for " + m); - TestFramework.check(ids.length > 0, "Did not find any rule indices for " + m); - TestFramework.check(ids[ids.length - 1] < irAnnos.length, "Invalid IR rule index found in validIrRulesMap for " + m); - if (ids[0] != IREncodingPrinter.NO_RULE_APPLIED) { - // If -1, than there was no matching IR rule for the given conditions. - compilations.put(m.getName(), new IRMethod(m, ids, irAnnos)); - } - } - } - } - - /** - * Read the IR encoding emitted by the test VM to decide if an @IR rule must be checked for a method. - */ - private Map parseIREncoding(String irEncoding) { - Map irRulesMap = new HashMap<>(); - Matcher matcher = IR_ENCODING_PATTERN.matcher(irEncoding); - TestFramework.check(matcher.find(), "Did not find IR encoding"); - String[] lines = matcher.group(0).split("\\R"); - - // Skip first line containing information about the format only - for (int i = 1; i < lines.length; i++) { - String line = lines[i].trim(); - String[] splitComma = line.split(","); - if (splitComma.length < 2) { - throw new TestFrameworkException("Invalid IR match rule encoding. No comma found: " + splitComma[0]); - } - String testName = splitComma[0]; - int[] irRulesIdx = new int[splitComma.length - 1]; - for (int j = 1; j < splitComma.length; j++) { - try { - irRulesIdx[j - 1] = Integer.parseInt(splitComma[j]); - } catch (NumberFormatException e) { - throw new TestFrameworkException("Invalid IR match rule encoding. No number found: " + splitComma[j]); - } - } - irRulesMap.put(testName, irRulesIdx); - } - return irRulesMap; - } - - /** - * Parse the hotspot_pid*.log file from the test VM. Read the PrintIdeal and PrintOptoAssembly entries for all - * methods of the test class that need to be IR matched (according to IR encoding). - */ - private void parseHotspotPidFile() { - Map compileIdMap = new HashMap<>(); - try (var br = Files.newBufferedReader(Paths.get(hotspotPidFileName))) { - String line; - StringBuilder builder = new StringBuilder(); - boolean append = false; - String currentMethod = ""; - while ((line = br.readLine()) != null) { - if (append && line.startsWith(" tag. - } - } else if (isPrintOptoAssemblyStart(line)) { - String methodName = getMethodName(compileIdMap, line); - if (methodName != null) { - TestFramework.check(compilations.containsKey(methodName), "Must be second entry of " + methodName); - currentMethod = methodName; - append = true; // Append all following lines until we hit the closing tag. - } - } - } - } catch (IOException e) { - throw new TestFrameworkException("Error while reading " + hotspotPidFileName, e); - } - } - - /** - * Write the input to the IR method and reset the builder. - */ - private void flushOutput(String line, StringBuilder builder, String currentMethod) { - TestFramework.check(!currentMethod.isEmpty(), "current method must be set"); - IRMethod irMethod = compilations.get(currentMethod); - if (line.startsWith(""); - line = line.replace(""", "\""); - line = line.replace("'", "'"); - line = line.replace("&", "&"); - } - builder.append(line).append(System.lineSeparator()); - } - - private static int getCompileId(Matcher matcher) { - int compileId; - try { - compileId = Integer.parseInt(matcher.group(1)); - } catch (NumberFormatException e) { - throw new TestRunException("Could not parse compile id", e); - } - return compileId; - } - - /** - * Parse the compile id from this line if it belongs to a method that needs to be IR tested (part of test class - * and IR encoding from the test VM specifies that this method has @IR rules to be checked). - */ - private void addTestMethodCompileId(Map compileIdMap, String line) { - Matcher matcher = compileIdPatternForTestClass.matcher(line); - if (matcher.find()) { - // Only care about test class entries. Might have non-class entries as well if user specified additional - // compile commands. Ignore these. - String methodName = matcher.group(2); - if (compilations.containsKey(methodName)) { - // We only care about methods that we are actually gonna IR match based on IR encoding. - int compileId = getCompileId(matcher); - TestRun.check(!methodName.isEmpty(), "method name cannot be empty"); - compileIdMap.put(compileId, methodName); - } - } - } - - /** - * Make sure that line does not contain compile_kind which is used for OSR compilations which we are not - * interested in. - */ - private static boolean isPrintIdealStart(String line) { - return line.startsWith(" compileIdMap, String line) { - Matcher matcher = COMPILE_ID_PATTERN.matcher(line); - TestFramework.check(matcher.find(), "Is " + hotspotPidFileName + " corrupted?"); - int compileId = getCompileId(matcher); - return compileIdMap.get(compileId); - } - - /** - * Do an IR matching of all methods with appliable @IR rules fetched during parsing of the hotspot pid file. - */ - private void applyRules() { - compilations.values().forEach(this::applyRulesForMethod); - reportFailuresIfAny(); - } - - private void applyRulesForMethod(IRMethod irMethod) { - this.irMethod = irMethod; - method = irMethod.getMethod(); - String testOutput = irMethod.getOutput(); - if (testOutput.isEmpty()) { - String msg = "Method was not compiled. Did you specify any compiler directives preventing a compilation or used a " + - "@Run method in STANDALONE mode? In the latter case, make sure to always trigger a C2 compilation " + - "by invoking the test enough times."; - fails.computeIfAbsent(method, k -> new ArrayList<>()).add(msg); - return; - } - - if (TestFramework.VERBOSE) { - System.out.println("Output of " + method + ":"); - System.out.println(testOutput); - } - Arrays.stream(irMethod.getRuleIds()).forEach(this::applyIRRule); - } - - /** - * Apply a single @IR rule as part of a method. - */ - private void applyIRRule(int id) { - irAnno = irMethod.getIrAnno(id); - irRuleIndex = id; - StringBuilder failMsg = new StringBuilder(); - applyFailOn(failMsg); - try { - applyCounts(failMsg); - } catch (TestFormatException e) { - // Logged. Continue to check other rules. - } - if (!failMsg.isEmpty()) { - failMsg.insert(0, "@IR rule " + (id + 1) + ": \"" + irAnno + "\"" + System.lineSeparator()); - fails.computeIfAbsent(method, k -> new ArrayList<>()).add(failMsg.toString()); - } - } - - /** - * Apply the failOn regexes of the @IR rule. - */ - private void applyFailOn(StringBuilder failMsg) { - if (irAnno.failOn().length != 0) { - String failOnRegex = String.join("|", IRNode.mergeNodes(irAnno.failOn())); - Pattern pattern = Pattern.compile(failOnRegex); - Matcher matcher = pattern.matcher(irMethod.getOutput()); - long matchCount = matcher.results().count(); - if (matchCount > 0) { - addFailOnFailsForOutput(failMsg, pattern, matchCount); - } - } - } - - /** - * A failOn regex failed. Apply all regexes again to log the exact regex which failed. The failure is later reported - * to the user. - */ - private void addFailOnFailsForOutput(StringBuilder failMsg, Pattern pattern, long matchCount) { - long idealCount = pattern.matcher(irMethod.getIdealOutput()).results().count(); - long optoAssemblyCount = pattern.matcher(irMethod.getOptoAssemblyOutput()).results().count(); - if (matchCount != idealCount + optoAssemblyCount || (idealCount != 0 && optoAssemblyCount != 0)) { - // Report with Ideal and Opto Assembly - addFailOnFailsForOutput(failMsg, irMethod.getOutput()); - irMethod.needsAllOutput(); - } else if (optoAssemblyCount == 0) { - // Report with Ideal only - addFailOnFailsForOutput(failMsg, irMethod.getIdealOutput()); - irMethod.needsIdeal(); - } else { - // Report with Opto Assembly only - addFailOnFailsForOutput(failMsg, irMethod.getOptoAssemblyOutput()); - irMethod.needsOptoAssembly(); - } - } - - /** - * Apply the regexes to the testOutput and log the failures. - */ - private void addFailOnFailsForOutput(StringBuilder failMsg, String testOutput) { - List failOnNodes = IRNode.mergeNodes(irAnno.failOn()); - Pattern pattern; - Matcher matcher; - failMsg.append("- failOn: Graph contains forbidden nodes:").append(System.lineSeparator()); - int nodeId = 1; - for (String nodeRegex : failOnNodes) { - pattern = Pattern.compile(nodeRegex); - matcher = pattern.matcher(testOutput); - long matchCount = matcher.results().count(); - if (matchCount > 0) { - matcher.reset(); - failMsg.append(" Regex ").append(nodeId).append(": ").append(nodeRegex).append(System.lineSeparator()); - failMsg.append(" Matched forbidden node").append(matchCount > 1 ? "s (" + matchCount + ")" : "") - .append(":").append(System.lineSeparator()); - matcher.results().forEach(r -> failMsg.append(" ").append(r.group()).append(System.lineSeparator())); - } - nodeId++; - } - } - - /** - * Apply the counts regexes of the @IR rule. - */ - private void applyCounts(StringBuilder failMsg) { - if (irAnno.counts().length != 0) { - boolean hasFails = false; - String testOutput = irMethod.getOutput(); - int countsId = 1; - final List nodesWithCount = IRNode.mergeNodes(irAnno.counts()); - for (int i = 0; i < nodesWithCount.size(); i += 2) { - String node = nodesWithCount.get(i); - TestFormat.check(i + 1 < nodesWithCount.size(), "Missing count" + getPostfixErrorMsg(node)); - String countString = nodesWithCount.get(i + 1); - long expectedCount; - ParsedComparator parsedComparator; - try { - parsedComparator = ParsedComparator.parseComparator(countString); - expectedCount = Long.parseLong(parsedComparator.getStrippedString()); - } catch (NumberFormatException e) { - TestFormat.fail("Provided invalid count \"" + countString + "\"" + getPostfixErrorMsg(node)); - return; - } catch (CheckedTestFrameworkException e) { - TestFormat.fail("Invalid comparator \"" + e.getMessage() + "\" in \"" + countString + "\" for count" + getPostfixErrorMsg(node)); - return; - } catch (IndexOutOfBoundsException e) { - TestFormat.fail("Provided empty value" + getPostfixErrorMsg(node)); - return; - } - TestFormat.check(expectedCount >= 0,"Provided invalid negative count \"" + countString + "\"" + getPostfixErrorMsg(node)); - - Pattern pattern = Pattern.compile(node); - Matcher matcher = pattern.matcher(testOutput); - long actualCount = matcher.results().count(); - if (!parsedComparator.getPredicate().test(actualCount, expectedCount)) { - if (!hasFails) { - failMsg.append("- counts: Graph contains wrong number of nodes:").append(System.lineSeparator()); - hasFails = true; - } - addCountsFail(failMsg, node, pattern, expectedCount, actualCount, countsId); - } - countsId++; - } - } - } - - private String getPostfixErrorMsg(String node) { - return " for IR rule " + irRuleIndex + ", node \"" + node + "\" at " + method; - } - - /** - * A counts regex failed. Apply all regexes again to log the exact regex which failed. The failure is later reported - * to the user. - */ - private void addCountsFail(StringBuilder failMsg, String node, Pattern pattern, long expectedCount, long actualCount, int countsId) { - failMsg.append(" Regex ").append(countsId).append(": ").append(node).append(System.lineSeparator()); - failMsg.append(" Expected ").append(expectedCount).append(" but found ").append(actualCount); - - if (actualCount > 0) { - Matcher matcher = pattern.matcher(irMethod.getOutput()); - long idealCount = pattern.matcher(irMethod.getIdealOutput()).results().count(); - long optoAssemblyCount = pattern.matcher(irMethod.getOptoAssemblyOutput()).results().count(); - if (actualCount != idealCount + optoAssemblyCount || (idealCount != 0 && optoAssemblyCount != 0)) { - irMethod.needsAllOutput(); - } else if (optoAssemblyCount == 0) { - irMethod.needsIdeal(); - } else { - irMethod.needsOptoAssembly(); - } - failMsg.append(" node").append(actualCount > 1 ? "s" : "").append(":").append(System.lineSeparator()); - matcher.results().forEach(r -> failMsg.append(" ").append(r.group()).append(System.lineSeparator())); - } else { - irMethod.needsAllOutput(); - failMsg.append(" nodes.").append(System.lineSeparator()); - } - } - - /** - * Report all IR violations in a pretty format to the user. Depending on the failed regex, we only report - * PrintIdeal or PrintOptoAssembly if the match failed there. If there were failures that matched things - * in both outputs than the entire output is reported. Throws IRViolationException from which the compilation - * can be read and reported to the stdout separately. The exception message only includes the summary of the - * failures. - */ - private void reportFailuresIfAny() { - TestFormat.reportIfAnyFailures(); - if (!fails.isEmpty()) { - StringBuilder failuresBuilder = new StringBuilder(); - StringBuilder compilationsBuilder = new StringBuilder(); - int failures = 0; - for (Map.Entry> entry : fails.entrySet()) { - Method method = entry.getKey(); - compilationsBuilder.append(">>> Compilation of ").append(method).append(":").append(System.lineSeparator()); - IRMethod irMethod = compilations.get(method.getName()); - String output; - if (irMethod.usesIdeal() && irMethod.usesOptoAssembly()) { - output = irMethod.getOutput(); - } else if (irMethod.usesIdeal()) { - output = irMethod.getIdealOutput(); - } else if (irMethod.usesOptoAssembly()) { - output = irMethod.getOptoAssemblyOutput(); - } else { - output = ""; - } - compilationsBuilder.append(output).append(System.lineSeparator()).append(System.lineSeparator()); - List list = entry.getValue(); - failuresBuilder.append("- Method \"").append(method).append("\":").append(System.lineSeparator()); - failures += list.size(); - list.forEach(s -> failuresBuilder.append(" * ") - .append(s.replace(System.lineSeparator(), - System.lineSeparator() + " ").trim()) - .append(System.lineSeparator())); - failuresBuilder.append(System.lineSeparator()); - } - failuresBuilder.insert(0, ("One or more @IR rules failed:" + System.lineSeparator() - + System.lineSeparator() + "Failed IR Rules (" + failures + ")" - + System.lineSeparator()) + "-----------------" - + "-".repeat(String.valueOf(failures).length()) + System.lineSeparator()); - failuresBuilder.append(">>> Check stdout for compilation output of the failed methods") - .append(System.lineSeparator()).append(System.lineSeparator()); - - // In some very rare cases, the VM output to regex match on contains "" - // (emitted by ttyLocker::break_tty_for_safepoint) which might be the reason for a matching error. - // Do not throw an exception in this case (i.e. bailout). - String compilations = compilationsBuilder.toString(); - if (!compilations.contains(SAFEPOINT_WHILE_PRINTING_MESSAGE)) { - throw new IRViolationException(failuresBuilder.toString(), compilations); - } else { - System.out.println("Found " + SAFEPOINT_WHILE_PRINTING_MESSAGE + ", bail out of IR matching"); - } - } - } -} diff --git a/test/hotspot/jtreg/compiler/lib/ir_framework/driver/TestVMProcess.java b/test/hotspot/jtreg/compiler/lib/ir_framework/driver/TestVMProcess.java index 0bec4c0e5da6d4403cb3605c518904ba3f4961ba..d8e10e763157730b315bf1b146ae039f59fad003 100644 --- a/test/hotspot/jtreg/compiler/lib/ir_framework/driver/TestVMProcess.java +++ b/test/hotspot/jtreg/compiler/lib/ir_framework/driver/TestVMProcess.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 @@ -194,13 +194,13 @@ public class TestVMProcess { if (!testListBuilder.isEmpty()) { System.out.println("Run flag defined test list"); System.out.println("--------------------------"); - System.out.println(testListBuilder.toString()); + System.out.println(testListBuilder); System.out.println(); } if (!messagesBuilder.isEmpty()) { System.out.println("Messages from Test VM"); System.out.println("---------------------"); - System.out.println(messagesBuilder.toString()); + System.out.println(messagesBuilder); } irEncoding = nonStdOutBuilder.toString(); } else { @@ -226,7 +226,7 @@ public class TestVMProcess { */ private void throwTestVMException() { String stdErr = oa.getStderr(); - if (stdErr.contains("TestFormat.reportIfAnyFailures")) { + if (stdErr.contains("TestFormat.throwIfAnyFailures")) { Pattern pattern = Pattern.compile("Violations \\(\\d+\\)[\\s\\S]*(?=/============/)"); Matcher matcher = pattern.matcher(stdErr); TestFramework.check(matcher.find(), "Must find violation matches"); diff --git a/test/hotspot/jtreg/compiler/lib/ir_framework/driver/irmatching/CompilationOutputBuilder.java b/test/hotspot/jtreg/compiler/lib/ir_framework/driver/irmatching/CompilationOutputBuilder.java new file mode 100644 index 0000000000000000000000000000000000000000..b93d238656432a8c7306cede28cb51a5d383cbb1 --- /dev/null +++ b/test/hotspot/jtreg/compiler/lib/ir_framework/driver/irmatching/CompilationOutputBuilder.java @@ -0,0 +1,50 @@ +/* + * 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.lib.ir_framework.driver.irmatching; + +import compiler.lib.ir_framework.driver.irmatching.irmethod.IRMethodMatchResult; + +import java.util.List; + +/** + * Class to build the compilation output of IR matching failures. + * + * @see IRMethodMatchResult + */ +class CompilationOutputBuilder { + + public static String build(List results) { + StringBuilder compilationsBuilder = new StringBuilder(); + for (IRMethodMatchResult result : results) { + if (result.fail()) { + compilationsBuilder.append(buildMatchedCompilationMessage(result)); + } + } + return compilationsBuilder.toString(); + } + + private static String buildMatchedCompilationMessage(IRMethodMatchResult result) { + return result.getMatchedCompilationOutput() + System.lineSeparator() + System.lineSeparator(); + } +} diff --git a/test/hotspot/jtreg/compiler/lib/ir_framework/driver/irmatching/IRMatcher.java b/test/hotspot/jtreg/compiler/lib/ir_framework/driver/irmatching/IRMatcher.java new file mode 100644 index 0000000000000000000000000000000000000000..c39d68ab1279dbb584f3e7652dfb456deee03c6a --- /dev/null +++ b/test/hotspot/jtreg/compiler/lib/ir_framework/driver/irmatching/IRMatcher.java @@ -0,0 +1,96 @@ +/* + * 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 compiler.lib.ir_framework.driver.irmatching; + +import compiler.lib.ir_framework.*; +import compiler.lib.ir_framework.driver.irmatching.irmethod.IRMethodMatchResult; +import compiler.lib.ir_framework.driver.irmatching.irmethod.IRMethod; +import compiler.lib.ir_framework.driver.irmatching.parser.IRMethodParser; + +import java.util.*; + +/** + * This class parses the hotspot_pid* file of the test VM to match all applicable @IR rules afterwards. + */ +public class IRMatcher { + public static final String SAFEPOINT_WHILE_PRINTING_MESSAGE = ""; + + public IRMatcher(String hotspotPidFileName, String irEncoding, Class testClass) { + IRMethodParser irMethodParser = new IRMethodParser(testClass); + Collection irMethods = irMethodParser.parse(hotspotPidFileName, irEncoding); + if (irMethods != null) { + applyIRRules(irMethods); + } + } + + /** + * Do an IR matching of all methods with applicable @IR rules prepared with by the {@link IRMethodParser}. + */ + private void applyIRRules(Collection irMethods) { + List results = new ArrayList<>(); + irMethods.forEach(irMethod -> applyIRRule(irMethod, results)); + if (!results.isEmpty()) { + reportFailures(results); + } + } + + private void applyIRRule(IRMethod irMethod, List results) { + if (TestFramework.VERBOSE) { + printMethodOutput(irMethod); + } + IRMethodMatchResult result = irMethod.applyIRRules(); + if (result.fail()) { + results.add(result); + } + } + + private void printMethodOutput(IRMethod irMethod) { + System.out.println("Output of " + irMethod.getOutput() + ":"); + System.out.println(irMethod.getOutput()); + } + + /** + * Report all IR violations in a pretty format to the user. Depending on the failed regex, we only report + * PrintIdeal or PrintOptoAssembly if the match failed there. If there were failures that matched things + * in both outputs then the entire output is reported. Throws IRViolationException from which the compilation + * can be read and reported to the stdout separately. The exception message only includes the summary of the + * failures. + */ + private void reportFailures(List results) { + Collections.sort(results); // Alphabetically + throwIfNoSafepointWhilePrinting(IRMatcherFailureMessageBuilder.build(results), + CompilationOutputBuilder.build(results)); + } + + // In some very rare cases, the VM output to regex match on contains "" + // (emitted by ttyLocker::break_tty_for_safepoint) which might be the reason for a matching error. + // Do not throw an exception in this case (i.e. bailout). + private void throwIfNoSafepointWhilePrinting(String failures, String compilations) { + if (!compilations.contains(SAFEPOINT_WHILE_PRINTING_MESSAGE)) { + throw new IRViolationException(failures, compilations); + } else { + System.out.println("Found " + SAFEPOINT_WHILE_PRINTING_MESSAGE + ", bail out of IR matching"); + } + } +} diff --git a/test/hotspot/jtreg/compiler/lib/ir_framework/driver/irmatching/IRMatcherFailureMessageBuilder.java b/test/hotspot/jtreg/compiler/lib/ir_framework/driver/irmatching/IRMatcherFailureMessageBuilder.java new file mode 100644 index 0000000000000000000000000000000000000000..4cdff9a2aae137d1d88cd224b7aeb33d46ef9f87 --- /dev/null +++ b/test/hotspot/jtreg/compiler/lib/ir_framework/driver/irmatching/IRMatcherFailureMessageBuilder.java @@ -0,0 +1,81 @@ +/* + * 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.lib.ir_framework.driver.irmatching; + +import compiler.lib.ir_framework.driver.irmatching.irmethod.IRMethodMatchResult; + +import java.util.List; + +/** + * Class to build the failure message output of IR matching failures. + * + * @see IRMethodMatchResult + */ +class IRMatcherFailureMessageBuilder { + + public static String build(List results) { + StringBuilder failuresBuilder = new StringBuilder(); + failuresBuilder.append(buildHeaderMessage(results)); + int failureNumber = 1; + for (IRMethodMatchResult irMethodResult : results) { + if (irMethodResult.fail()) { + failuresBuilder.append(buildIRMethodFailureMessage(failureNumber, irMethodResult)); + failureNumber++; + } + } + failuresBuilder.append(buildFooterMessage()); + return failuresBuilder.toString(); + } + + private static String buildHeaderMessage(List results) { + int failedIRRulesCount = getFailedIRRulesCount(results); + long failedMethodCount = getFailedMethodCount(results); + return "One or more @IR rules failed:" + System.lineSeparator() + System.lineSeparator() + + "Failed IR Rules (" + failedIRRulesCount + ") of Methods (" + failedMethodCount + ")" + + System.lineSeparator() + + "-".repeat(32 + digitCount(failedIRRulesCount) + digitCount(failedMethodCount)) + + System.lineSeparator(); + } + + private static int getFailedIRRulesCount(List results) { + return results.stream().map(IRMethodMatchResult::getFailedIRRuleCount).reduce(0, Integer::sum); + } + + private static long getFailedMethodCount(List results) { + return results.stream().filter(IRMethodMatchResult::fail).count(); + } + + private static int digitCount(long digit) { + return String.valueOf(digit).length(); + } + + private static String buildIRMethodFailureMessage(int failureNumber, IRMethodMatchResult result) { + return failureNumber + ")" + result.buildFailureMessage() + System.lineSeparator(); + } + + private static String buildFooterMessage() { + return ">>> Check stdout for compilation output of the failed methods" + System.lineSeparator() + System.lineSeparator(); + } + +} diff --git a/test/hotspot/jtreg/compiler/lib/ir_framework/driver/IRViolationException.java b/test/hotspot/jtreg/compiler/lib/ir_framework/driver/irmatching/IRViolationException.java similarity index 94% rename from test/hotspot/jtreg/compiler/lib/ir_framework/driver/IRViolationException.java rename to test/hotspot/jtreg/compiler/lib/ir_framework/driver/irmatching/IRViolationException.java index bacf3536dada5568f72ccc5ffb4e21b0672c7fd7..c11de93df0609d59bdd93d9f4c5dcb5a4fd3eb46 100644 --- a/test/hotspot/jtreg/compiler/lib/ir_framework/driver/IRViolationException.java +++ b/test/hotspot/jtreg/compiler/lib/ir_framework/driver/irmatching/IRViolationException.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 @@ -21,7 +21,7 @@ * questions. */ -package compiler.lib.ir_framework.driver; +package compiler.lib.ir_framework.driver.irmatching; import compiler.lib.ir_framework.IR; import compiler.lib.ir_framework.Test; diff --git a/test/hotspot/jtreg/compiler/lib/ir_framework/driver/irmatching/MatchResult.java b/test/hotspot/jtreg/compiler/lib/ir_framework/driver/irmatching/MatchResult.java new file mode 100644 index 0000000000000000000000000000000000000000..bc892505f879b9e8e9990250bae2c6d76a11db04 --- /dev/null +++ b/test/hotspot/jtreg/compiler/lib/ir_framework/driver/irmatching/MatchResult.java @@ -0,0 +1,40 @@ +/* + * 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.lib.ir_framework.driver.irmatching; + +/** + * Interface used by all classes which represent a IR match result. A result should also provide a failure message + * in a pretty format to be used by the {@link IRMatcher}. + */ +public interface MatchResult { + /** + * Does this match result represent a failure? + */ + boolean fail(); + + /** + * Builds a failure message in a pretty format to be used by the IR matching failure reporting. + */ + String buildFailureMessage(); +} diff --git a/test/hotspot/jtreg/compiler/lib/ir_framework/driver/irmatching/OutputMatch.java b/test/hotspot/jtreg/compiler/lib/ir_framework/driver/irmatching/OutputMatch.java new file mode 100644 index 0000000000000000000000000000000000000000..85cc81725ed543b7eee0c954f7c67b13750affca --- /dev/null +++ b/test/hotspot/jtreg/compiler/lib/ir_framework/driver/irmatching/OutputMatch.java @@ -0,0 +1,50 @@ +/* + * 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.lib.ir_framework.driver.irmatching; + +import compiler.lib.ir_framework.driver.irmatching.irrule.IRRuleMatchResult; + +/** + * Enum to describe what kind of compilation output that was matched for a method during IR matching. + * + * @see IRRuleMatchResult + */ +public enum OutputMatch { + /** + * There was no compilation output. Should not happen and results in a failure. + */ + NONE, + /** + * Matched on PrintIdeal. + */ + IDEAL, + /** + * Matched on PrintOptoAssembly. + */ + OPTO_ASSEMBLY, + /** + * Matched on PrintIdeal and PrintOptoAssembly. + */ + BOTH +} diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/gc/shared/CardGeneration.java b/test/hotspot/jtreg/compiler/lib/ir_framework/driver/irmatching/irmethod/FailureMessageBuilder.java similarity index 64% rename from src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/gc/shared/CardGeneration.java rename to test/hotspot/jtreg/compiler/lib/ir_framework/driver/irmatching/irmethod/FailureMessageBuilder.java index 3d96d33d81e8974677bbfb23676689472da2c895..057a4cd8ce9301f9f581322212150d4c878b4a86 100644 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/gc/shared/CardGeneration.java +++ b/test/hotspot/jtreg/compiler/lib/ir_framework/driver/irmatching/irmethod/FailureMessageBuilder.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2015, 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 @@ -19,22 +19,25 @@ * 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; +package compiler.lib.ir_framework.driver.irmatching.irmethod; + +import compiler.lib.ir_framework.driver.irmatching.irrule.IRRuleMatchResult; -import sun.jvm.hotspot.debugger.*; +import java.util.List; -/** Class CardGeneration is a generation that is covered by a card - table, and uses a card-size block-offset array to implement - block_start. */ +/** + * Base class to build the failure message output for an IR method. + * + * @see IRMethodMatchResult + */ +abstract class FailureMessageBuilder { + protected final IRMethod irMethod; -public abstract class CardGeneration extends Generation { - public CardGeneration(Address addr) { - super(addr); - } + public FailureMessageBuilder(IRMethod irMethod) { + this.irMethod = irMethod; + } - // FIXME: not sure what I need to expose from here in order to have - // verification similar to that of the old RememberedSet + abstract public String build(); } diff --git a/test/hotspot/jtreg/compiler/lib/ir_framework/driver/IRMethod.java b/test/hotspot/jtreg/compiler/lib/ir_framework/driver/irmatching/irmethod/IRMethod.java similarity index 66% rename from test/hotspot/jtreg/compiler/lib/ir_framework/driver/IRMethod.java rename to test/hotspot/jtreg/compiler/lib/ir_framework/driver/irmatching/irmethod/IRMethod.java index dbad17034afee3b81c157d70f95175c7eeb83f1d..3250f825e00196ca68db18429416b385eefa5fc9 100644 --- a/test/hotspot/jtreg/compiler/lib/ir_framework/driver/IRMethod.java +++ b/test/hotspot/jtreg/compiler/lib/ir_framework/driver/irmatching/irmethod/IRMethod.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 @@ -21,30 +21,34 @@ * questions. */ -package compiler.lib.ir_framework.driver; +package compiler.lib.ir_framework.driver.irmatching.irmethod; import compiler.lib.ir_framework.IR; +import compiler.lib.ir_framework.TestFramework; +import compiler.lib.ir_framework.driver.irmatching.irrule.IRRule; +import compiler.lib.ir_framework.driver.irmatching.irrule.IRRuleMatchResult; import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.List; /** * Helper class to store information about a method that needs to be IR matched. */ -class IRMethod { +public class IRMethod { private final Method method; - private final int[] ruleIds; - private final IR[] irAnnos; + private final List irRules; private final StringBuilder outputBuilder; private String output; private String idealOutput; private String optoAssemblyOutput; - private boolean needsIdeal; - private boolean needsOptoAssembly; public IRMethod(Method method, int[] ruleIds, IR[] irAnnos) { this.method = method; - this.ruleIds = ruleIds; - this.irAnnos = irAnnos; + this.irRules = new ArrayList<>(); + for (int i : ruleIds) { + irRules.add(new IRRule(this, i, irAnnos[i - 1])); + } this.outputBuilder = new StringBuilder(); this.output = ""; this.idealOutput = ""; @@ -55,13 +59,6 @@ class IRMethod { return method; } - public int[] getRuleIds() { - return ruleIds; - } - - public IR getIrAnno(int idx) { - return irAnnos[idx]; - } /** * The Ideal output comes always before the Opto Assembly output. We might parse multiple C2 compilations of this method. @@ -94,24 +91,26 @@ class IRMethod { return optoAssemblyOutput; } - public void needsAllOutput() { - needsIdeal(); - needsOptoAssembly(); - } - - public void needsIdeal() { - needsIdeal = true; - } - - public boolean usesIdeal() { - return needsIdeal; - } - - public void needsOptoAssembly() { - needsOptoAssembly = true; + /** + * Apply all IR rules of this IR method. + */ + public IRMethodMatchResult applyIRRules() { + TestFramework.check(!irRules.isEmpty(), "IRMethod cannot be created if there are no IR rules to apply"); + List results = new ArrayList<>(); + if (!output.isEmpty()) { + return getNormalMatchResult(results); + } else { + return new MissingCompilationResult(this, irRules.size()); + } } - public boolean usesOptoAssembly() { - return needsOptoAssembly; + private NormalMatchResult getNormalMatchResult(List results) { + for (IRRule irRule : irRules) { + IRRuleMatchResult result = irRule.applyCheckAttribute(); + if (result.fail()) { + results.add(result); + } + } + return new NormalMatchResult(this, results); } } diff --git a/test/hotspot/jtreg/compiler/lib/ir_framework/driver/irmatching/irmethod/IRMethodMatchResult.java b/test/hotspot/jtreg/compiler/lib/ir_framework/driver/irmatching/irmethod/IRMethodMatchResult.java new file mode 100644 index 0000000000000000000000000000000000000000..78e4dec5fee3ce15d7bbb0954052baecbbab95ac --- /dev/null +++ b/test/hotspot/jtreg/compiler/lib/ir_framework/driver/irmatching/irmethod/IRMethodMatchResult.java @@ -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. + */ + +package compiler.lib.ir_framework.driver.irmatching.irmethod; + +import compiler.lib.ir_framework.driver.irmatching.MatchResult; +import compiler.lib.ir_framework.driver.irmatching.irrule.IRRuleMatchResult; + +/** + * This base class represents an IR matching result of all IR rules of a method. + * + * @see IRRuleMatchResult + * @see IRMethod + */ +abstract public class IRMethodMatchResult implements Comparable, MatchResult { + protected final IRMethod irMethod; + + IRMethodMatchResult(IRMethod irMethod) { + this.irMethod = irMethod; + } + + abstract public String getMatchedCompilationOutput(); + + abstract public int getFailedIRRuleCount(); + + /** + * Used to sort the failed IR methods alphabetically. + */ + @Override + public int compareTo(IRMethodMatchResult other) { + return this.irMethod.getMethod().getName().compareTo(other.irMethod.getMethod().getName()); + } +} diff --git a/test/hotspot/jtreg/compiler/lib/ir_framework/driver/irmatching/irmethod/MatchedCompilationOutputBuilder.java b/test/hotspot/jtreg/compiler/lib/ir_framework/driver/irmatching/irmethod/MatchedCompilationOutputBuilder.java new file mode 100644 index 0000000000000000000000000000000000000000..d58bdc1fd3634d0efe021e13df03de8e9674e267 --- /dev/null +++ b/test/hotspot/jtreg/compiler/lib/ir_framework/driver/irmatching/irmethod/MatchedCompilationOutputBuilder.java @@ -0,0 +1,77 @@ +/* + * 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.lib.ir_framework.driver.irmatching.irmethod; + +import compiler.lib.ir_framework.driver.irmatching.OutputMatch; +import compiler.lib.ir_framework.driver.irmatching.irrule.IRRuleMatchResult; +import compiler.lib.ir_framework.shared.TestFrameworkException; + +import java.util.List; + +/** + * Class to build the compilation output for an IR method. + * + * @see IRMethodMatchResult + */ +class MatchedCompilationOutputBuilder { + private final IRMethod irMethod; + private final OutputMatch outputMatch; + + public MatchedCompilationOutputBuilder(IRMethod irMethod, List irRulesMatchResults) { + this.irMethod = irMethod; + this.outputMatch = getOutputMatch(irRulesMatchResults); + } + + private OutputMatch getOutputMatch(List irRulesMatchResults) { + OutputMatch outputMatch; + if (allMatchesOn(irRulesMatchResults, OutputMatch.IDEAL)) { + outputMatch = OutputMatch.IDEAL; + } else if (allMatchesOn(irRulesMatchResults, OutputMatch.OPTO_ASSEMBLY)) { + outputMatch = OutputMatch.OPTO_ASSEMBLY; + } else { + outputMatch = OutputMatch.BOTH; + } + return outputMatch; + } + + private boolean allMatchesOn(List irRulesMatchResults, OutputMatch outputMatch) { + return irRulesMatchResults.stream().allMatch(r -> r.getOutputMatch() == outputMatch); + } + + public String build() { + StringBuilder builder = new StringBuilder(); + builder.append(getMethodLine()); + switch (outputMatch) { + case IDEAL -> builder.append(irMethod.getIdealOutput()); + case OPTO_ASSEMBLY -> builder.append(irMethod.getOptoAssemblyOutput()); + case BOTH -> builder.append(irMethod.getOutput()); + default -> throw new TestFrameworkException("found unexpected OutputMatch " + outputMatch.name()); + } + return builder.toString(); + } + + private String getMethodLine() { + return ">>> Compilation of " + irMethod.getMethod() + ":" + System.lineSeparator(); + } +} diff --git a/test/hotspot/jtreg/compiler/lib/ir_framework/driver/irmatching/irmethod/MissingCompilationMessageBuilder.java b/test/hotspot/jtreg/compiler/lib/ir_framework/driver/irmatching/irmethod/MissingCompilationMessageBuilder.java new file mode 100644 index 0000000000000000000000000000000000000000..7d3097640ebede3093e179fb4465c558d4809929 --- /dev/null +++ b/test/hotspot/jtreg/compiler/lib/ir_framework/driver/irmatching/irmethod/MissingCompilationMessageBuilder.java @@ -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. + * + * 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.lib.ir_framework.driver.irmatching.irmethod; + +import compiler.lib.ir_framework.driver.irmatching.irrule.IRRuleMatchResult; + +import java.util.List; + +/** + * Class to build the failure message output for an IR method with a missing compilation output. + * + * @see IRMethodMatchResult + */ +class MissingCompilationMessageBuilder extends FailureMessageBuilder { + + public MissingCompilationMessageBuilder(IRMethod irMethod) { + super(irMethod); + } + + @Override + public String build() { + return getMethodLine() + getMissingCompilationMessage(); + } + + private String getMissingCompilationMessage() { + return " * Method was not compiled. Did you specify any compiler directives preventing a compilation " + + "or used a @Run method in STANDALONE mode? In the latter case, make sure to always trigger a C2 " + + "compilation by " + "invoking the test enough times."; + } + private String getMethodLine() { + return " Method \"" + irMethod.getMethod() + "\":" + System.lineSeparator(); + } +} diff --git a/test/hotspot/jtreg/compiler/lib/ir_framework/driver/irmatching/irmethod/MissingCompilationResult.java b/test/hotspot/jtreg/compiler/lib/ir_framework/driver/irmatching/irmethod/MissingCompilationResult.java new file mode 100644 index 0000000000000000000000000000000000000000..16e008f247a1d5b0b57e86664302986f4481ab26 --- /dev/null +++ b/test/hotspot/jtreg/compiler/lib/ir_framework/driver/irmatching/irmethod/MissingCompilationResult.java @@ -0,0 +1,68 @@ +/* + * 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.lib.ir_framework.driver.irmatching.irmethod; + +import compiler.lib.ir_framework.driver.irmatching.irrule.IRRuleMatchResult; + +/** + * This class represents an IR matching result where the compilation output was empty. + * + * @see IRRuleMatchResult + * @see IRMethod + */ +public class MissingCompilationResult extends IRMethodMatchResult { + private final int failedIRRules; + private final MissingCompilationMessageBuilder failureMessageBuilder; + + MissingCompilationResult(IRMethod irMethod, int failedIRRules) { + super(irMethod); + this.failedIRRules = failedIRRules; + this.failureMessageBuilder = new MissingCompilationMessageBuilder(irMethod); + } + + @Override + public boolean fail() { + return true; + } + + @Override + public String getMatchedCompilationOutput() { + return ""; + } + + @Override + public String buildFailureMessage() { + return failureMessageBuilder.build(); + } + + private String getMethodLine() { + return " Method \"" + irMethod.getMethod() + "\":" + System.lineSeparator(); + } + + @Override + public int getFailedIRRuleCount() { + return failedIRRules; + } + +} diff --git a/test/hotspot/jtreg/compiler/lib/ir_framework/driver/irmatching/irmethod/NormalFailureMessageBuilder.java b/test/hotspot/jtreg/compiler/lib/ir_framework/driver/irmatching/irmethod/NormalFailureMessageBuilder.java new file mode 100644 index 0000000000000000000000000000000000000000..a6d202407ef98cb1f3ea1d7f15701dbe1ec19eff --- /dev/null +++ b/test/hotspot/jtreg/compiler/lib/ir_framework/driver/irmatching/irmethod/NormalFailureMessageBuilder.java @@ -0,0 +1,64 @@ +/* + * 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.lib.ir_framework.driver.irmatching.irmethod; + +import compiler.lib.ir_framework.driver.irmatching.irrule.IRRuleMatchResult; + +import java.util.List; +import java.util.stream.Collectors; + +/** + * Class to build the failure message output for an IR method for failed IR rules. + * + * @see IRMethodMatchResult + */ +class NormalFailureMessageBuilder extends FailureMessageBuilder { + private final List irRulesMatchResults; + + public NormalFailureMessageBuilder(IRMethod irMethod, List irRulesMatchResults) { + super(irMethod); + this.irRulesMatchResults = irRulesMatchResults.stream() + .filter(IRRuleMatchResult::fail) + .collect(Collectors.toList()); + } + + @Override + public String build() { + return getMethodLine() + getIRRulesFailureMessage(); + } + + private String getMethodLine() { + int failures = irRulesMatchResults.size(); + return " Method \"" + irMethod.getMethod() + "\" - [Failed IR rules: " + failures + "]:" + + System.lineSeparator(); + } + + private String getIRRulesFailureMessage() { + StringBuilder failMsg = new StringBuilder(); + for (IRRuleMatchResult irRuleResult : irRulesMatchResults) { + failMsg.append(irRuleResult.buildFailureMessage()); + } + return failMsg.toString(); + } +} diff --git a/test/hotspot/jtreg/compiler/lib/ir_framework/driver/irmatching/irmethod/NormalMatchResult.java b/test/hotspot/jtreg/compiler/lib/ir_framework/driver/irmatching/irmethod/NormalMatchResult.java new file mode 100644 index 0000000000000000000000000000000000000000..280f2909fcff78312d532d2f0fc7e6bb9e987395 --- /dev/null +++ b/test/hotspot/jtreg/compiler/lib/ir_framework/driver/irmatching/irmethod/NormalMatchResult.java @@ -0,0 +1,67 @@ +/* + * 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.lib.ir_framework.driver.irmatching.irmethod; + +import compiler.lib.ir_framework.driver.irmatching.irrule.IRRuleMatchResult; + +import java.util.List; + +/** + * This class represents a normal IR matching result of all IR rules of a method. + * + * @see IRRuleMatchResult + * @see IRMethod + */ +class NormalMatchResult extends IRMethodMatchResult { + private final List irRulesMatchResults; + private final NormalFailureMessageBuilder failureMessageBuilder; + private final MatchedCompilationOutputBuilder matchedCompilationOutputBuilder; + + NormalMatchResult(IRMethod irMethod, List irRulesMatchResults) { + super(irMethod); + this.irRulesMatchResults = irRulesMatchResults; + this.failureMessageBuilder = new NormalFailureMessageBuilder(irMethod, irRulesMatchResults); + this.matchedCompilationOutputBuilder = new MatchedCompilationOutputBuilder(irMethod, irRulesMatchResults); + } + + @Override + public boolean fail() { + return !irRulesMatchResults.isEmpty(); + } + + @Override + public String getMatchedCompilationOutput() { + return matchedCompilationOutputBuilder.build(); + } + + @Override + public String buildFailureMessage() { + return failureMessageBuilder.build(); + } + + @Override + public int getFailedIRRuleCount() { + return irRulesMatchResults.size(); + } +} diff --git a/test/hotspot/jtreg/compiler/lib/ir_framework/driver/irmatching/irrule/CheckAttribute.java b/test/hotspot/jtreg/compiler/lib/ir_framework/driver/irmatching/irrule/CheckAttribute.java new file mode 100644 index 0000000000000000000000000000000000000000..a22a43a3871acb665301a233155029eac0be90d5 --- /dev/null +++ b/test/hotspot/jtreg/compiler/lib/ir_framework/driver/irmatching/irrule/CheckAttribute.java @@ -0,0 +1,48 @@ +/* + * 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.lib.ir_framework.driver.irmatching.irrule; + +import compiler.lib.ir_framework.IR; + +import java.util.ArrayList; +import java.util.List; +import java.util.regex.Matcher; + +/** + * Base class representing a check attribute of an IR rule. + * + * @see IR + */ +abstract class CheckAttribute { + + abstract public CheckAttributeMatchResult apply(String compilation); + + protected List getMatchedNodes(Matcher m) { + List matches = new ArrayList<>(); + do { + matches.add(m.group()); + } while (m.find()); + return matches; + } +} diff --git a/test/hotspot/jtreg/compiler/lib/ir_framework/driver/irmatching/irrule/CheckAttributeMatchResult.java b/test/hotspot/jtreg/compiler/lib/ir_framework/driver/irmatching/irrule/CheckAttributeMatchResult.java new file mode 100644 index 0000000000000000000000000000000000000000..8307957a60cec3fb0f77b636c61d41b1a521310c --- /dev/null +++ b/test/hotspot/jtreg/compiler/lib/ir_framework/driver/irmatching/irrule/CheckAttributeMatchResult.java @@ -0,0 +1,59 @@ +/* + * 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.lib.ir_framework.driver.irmatching.irrule; + +import compiler.lib.ir_framework.IR; +import compiler.lib.ir_framework.driver.irmatching.MatchResult; + +import java.util.List; + +/** + * Base class representing a result of an applied check attribute of an IR rule. + * + * @see IR + */ +abstract class CheckAttributeMatchResult implements MatchResult { + protected List regexFailures = null; + + @Override + public boolean fail() { + return regexFailures != null; + } + + public int getMatchesCount() { + if (fail()) { + return regexFailures.stream().map(RegexFailure::getMatchesCount).reduce(0, Integer::sum); + } else { + return 0; + } + } + + protected String collectRegexFailureMessages() { + StringBuilder failMsg = new StringBuilder(); + for (RegexFailure regexFailure : regexFailures) { + failMsg.append(regexFailure.buildFailureMessage()); + } + return failMsg.toString(); + } +} diff --git a/test/hotspot/jtreg/compiler/lib/ir_framework/driver/irmatching/irrule/Counts.java b/test/hotspot/jtreg/compiler/lib/ir_framework/driver/irmatching/irrule/Counts.java new file mode 100644 index 0000000000000000000000000000000000000000..4bda941c887743dd4041f14492190cc75cf6866d --- /dev/null +++ b/test/hotspot/jtreg/compiler/lib/ir_framework/driver/irmatching/irrule/Counts.java @@ -0,0 +1,121 @@ +/* + * 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.lib.ir_framework.driver.irmatching.irrule; + +import compiler.lib.ir_framework.IR; +import compiler.lib.ir_framework.shared.Comparison; +import compiler.lib.ir_framework.shared.ComparisonConstraintParser; +import compiler.lib.ir_framework.shared.TestFormat; + +import java.util.ArrayList; +import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * Class representing a counts attribute of an IR rule. + * + * @see IR#counts() + */ +class Counts extends CheckAttribute { + public List constraints; + + private Counts(List constraints) { + this.constraints = constraints; + } + + public static Counts create(List nodesWithCountConstraint, IRRule irRule) { + List constraints = new ArrayList<>(); + int nodeId = 1; + for (int i = 0; i < nodesWithCountConstraint.size(); i += 2, nodeId++) { + String node = nodesWithCountConstraint.get(i); + TestFormat.check(i + 1 < nodesWithCountConstraint.size(), + "Missing count " + getPostfixErrorMsg(irRule, node)); + String countConstraint = nodesWithCountConstraint.get(i + 1); + Comparison comparison = parseComparison(irRule, node, countConstraint); + constraints.add(new Constraint(node, comparison, nodeId)); + } + return new Counts(constraints); + } + + private static String getPostfixErrorMsg(IRRule irRule, String node) { + return "for IR rule " + irRule.getRuleId() + ", node \"" + node + "\" at " + irRule.getMethod(); + } + + private static Comparison parseComparison(IRRule irRule, String node, String constraint) { + String postfixErrorMsg = "in count constraint " + getPostfixErrorMsg(irRule, node); + return ComparisonConstraintParser.parse(constraint, Long::parseLong, postfixErrorMsg); + } + + @Override + public CheckAttributeMatchResult apply(String compilation) { + CountsMatchResult result = new CountsMatchResult(); + checkConstraints(result, compilation); + return result; + } + + private void checkConstraints(CountsMatchResult result, String compilation) { + for (Constraint constraint : constraints) { + checkConstraint(result, compilation, constraint); + } + } + + private void checkConstraint(CountsMatchResult result, String compilation, Constraint constraint) { + long foundCount = getFoundCount(compilation, constraint); + Comparison comparison = constraint.comparison; + if (!comparison.compare(foundCount)) { + result.addFailure(createRegexFailure(compilation, constraint, foundCount)); + } + } + + private long getFoundCount(String compilation, Constraint constraint) { + Pattern pattern = Pattern.compile(constraint.nodeRegex); + Matcher matcher = pattern.matcher(compilation); + return matcher.results().count(); + } + + private CountsRegexFailure createRegexFailure(String compilation, Constraint constraint, long foundCount) { + Pattern p = Pattern.compile(constraint.nodeRegex); + Matcher m = p.matcher(compilation); + List matches; + if (m.find()) { + matches = getMatchedNodes(m); + } else { + matches = new ArrayList<>(); + } + return new CountsRegexFailure(constraint.nodeRegex, constraint.nodeId, foundCount, constraint.comparison, matches); + } + + static class Constraint { + final String nodeRegex; + final Comparison comparison; + private final int nodeId; + + Constraint(String nodeRegex, Comparison comparison, int nodeId) { + this.nodeRegex = nodeRegex; + this.comparison = comparison; + this.nodeId = nodeId; + } + } +} diff --git a/test/hotspot/jtreg/compiler/lib/ir_framework/driver/irmatching/irrule/CountsMatchResult.java b/test/hotspot/jtreg/compiler/lib/ir_framework/driver/irmatching/irrule/CountsMatchResult.java new file mode 100644 index 0000000000000000000000000000000000000000..4830bb1b46af92f8f298f78d193371b6b4d6489b --- /dev/null +++ b/test/hotspot/jtreg/compiler/lib/ir_framework/driver/irmatching/irrule/CountsMatchResult.java @@ -0,0 +1,49 @@ +/* + * 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.lib.ir_framework.driver.irmatching.irrule; + +import compiler.lib.ir_framework.IR; + +import java.util.ArrayList; + +/** + * Class representing a result of an applied counts attribute of an IR rule. + * + * @see IR#counts() + */ +class CountsMatchResult extends CheckAttributeMatchResult { + + public void addFailure(RegexFailure regexFailure) { + if (regexFailures == null) { + regexFailures = new ArrayList<>(); + } + regexFailures.add(regexFailure); + } + + @Override + public String buildFailureMessage() { + return " - counts: Graph contains wrong number of nodes:" + System.lineSeparator() + + collectRegexFailureMessages(); + } +} diff --git a/test/hotspot/jtreg/compiler/lib/ir_framework/driver/irmatching/irrule/CountsRegexFailure.java b/test/hotspot/jtreg/compiler/lib/ir_framework/driver/irmatching/irrule/CountsRegexFailure.java new file mode 100644 index 0000000000000000000000000000000000000000..ae7b235ffd0dac52a1f598d2b5c215d59361154f --- /dev/null +++ b/test/hotspot/jtreg/compiler/lib/ir_framework/driver/irmatching/irrule/CountsRegexFailure.java @@ -0,0 +1,73 @@ +/* + * 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.lib.ir_framework.driver.irmatching.irrule; + +import compiler.lib.ir_framework.shared.Comparison; + +import java.util.List; + +/** + * This class represents an IR matching failure of a regex of a counts attribute of an IR rule. + * + * @see Counts + */ +class CountsRegexFailure extends RegexFailure { + String failedComparison; + + public CountsRegexFailure(String nodeRegex, int nodeId, long foundValue, Comparison comparison, List matches) { + super(nodeRegex, nodeId, matches); + this.failedComparison = "[found] " + foundValue + " " + comparison.getComparator() + " " + + comparison.getGivenValue() + " [given]"; + } + + @Override + public String buildFailureMessage() { + return getRegexLine() + + getFailedComparison() + + getMatchedNodesBlock(); + } + + private String getFailedComparison() { + return " - Failed comparison: " + failedComparison + System.lineSeparator(); + } + + @Override + protected String getMatchedNodesBlock() { + if (matches.isEmpty()) { + return getEmptyNodeMatchesLine(); + } else { + return super.getMatchedNodesBlock(); + } + } + + private String getEmptyNodeMatchesLine() { + return getMatchedNodesWhiteSpace() + "- No nodes matched!" + System.lineSeparator(); + } + + @Override + protected String getMatchedPrefix() { + return "Matched"; + } + +} diff --git a/test/hotspot/jtreg/compiler/lib/ir_framework/driver/irmatching/irrule/FailOn.java b/test/hotspot/jtreg/compiler/lib/ir_framework/driver/irmatching/irrule/FailOn.java new file mode 100644 index 0000000000000000000000000000000000000000..fa49a029ef9efbaef969e51f36139d2a3b8be9bc --- /dev/null +++ b/test/hotspot/jtreg/compiler/lib/ir_framework/driver/irmatching/irrule/FailOn.java @@ -0,0 +1,73 @@ +/* + * 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.lib.ir_framework.driver.irmatching.irrule; + +import compiler.lib.ir_framework.IR; + +import java.util.ArrayList; +import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * Class representing a failOn attribute of an IR rule. + * + * @see IR#failOn() + */ +class FailOn extends CheckAttribute { + private final Pattern quickPattern; + private final List nodes; + + public FailOn(List nodes) { + this.nodes = nodes; + this.quickPattern = Pattern.compile(String.join("|", nodes)); + } + + @Override + public CheckAttributeMatchResult apply(String compilation) { + FailOnMatchResult result = new FailOnMatchResult(); + Matcher matcher = quickPattern.matcher(compilation); + if (matcher.find()) { + result.setFailures(createFailOnFailures(compilation)); + } + return result; + } + + private List createFailOnFailures(String compilation) { + List regexFailures = new ArrayList<>(); + for (int i = 0; i < nodes.size(); i++) { + checkNode(regexFailures, compilation, nodes.get(i), i + 1); + } + return regexFailures; + } + + private void checkNode(List regexFailures, String compilation, String node, int nodeId) { + Pattern p = Pattern.compile(node); + Matcher m = p.matcher(compilation); + if (m.find()) { + List matches = getMatchedNodes(m); + regexFailures.add(new FailOnRegexFailure(node, nodeId, matches)); + } + } +} diff --git a/test/hotspot/jtreg/compiler/lib/ir_framework/driver/irmatching/irrule/FailOnMatchResult.java b/test/hotspot/jtreg/compiler/lib/ir_framework/driver/irmatching/irrule/FailOnMatchResult.java new file mode 100644 index 0000000000000000000000000000000000000000..99c6312ee02b278312f06dcd1609b54e698dcf05 --- /dev/null +++ b/test/hotspot/jtreg/compiler/lib/ir_framework/driver/irmatching/irrule/FailOnMatchResult.java @@ -0,0 +1,45 @@ +/* + * 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.lib.ir_framework.driver.irmatching.irrule; + +import compiler.lib.ir_framework.IR; + +import java.util.List; + +/** + * Class representing a result of an applied failOn attribute of an IR rule. + * + * @see IR#failOn() + */ +class FailOnMatchResult extends CheckAttributeMatchResult { + public void setFailures(List regexFailures) { + this.regexFailures = regexFailures; + } + + @Override + public String buildFailureMessage() { + return " - failOn: Graph contains forbidden nodes:" + System.lineSeparator() + + collectRegexFailureMessages(); + } +} diff --git a/test/hotspot/jtreg/compiler/lib/ir_framework/driver/irmatching/irrule/FailOnRegexFailure.java b/test/hotspot/jtreg/compiler/lib/ir_framework/driver/irmatching/irrule/FailOnRegexFailure.java new file mode 100644 index 0000000000000000000000000000000000000000..24c96aef5e9a2029acb26489ab67450db3c538cc --- /dev/null +++ b/test/hotspot/jtreg/compiler/lib/ir_framework/driver/irmatching/irrule/FailOnRegexFailure.java @@ -0,0 +1,49 @@ +/* + * 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.lib.ir_framework.driver.irmatching.irrule; + +import java.util.List; + +/** + * This class represents an IR matching failure of a regex of a failOn attribute of an IR rule. + * + * @see FailOn + */ +class FailOnRegexFailure extends RegexFailure { + + public FailOnRegexFailure(String nodeRegex, int nodeId, List matches) { + super(nodeRegex, nodeId, matches); + } + + @Override + public String buildFailureMessage() { + return getRegexLine() + + getMatchedNodesBlock(); + } + + @Override + protected String getMatchedPrefix() { + return "Matched forbidden"; + } +} diff --git a/test/hotspot/jtreg/compiler/lib/ir_framework/driver/irmatching/irrule/IRRule.java b/test/hotspot/jtreg/compiler/lib/ir_framework/driver/irmatching/irrule/IRRule.java new file mode 100644 index 0000000000000000000000000000000000000000..5b2e8c7718adc09012d8cea990b989f43cf5e54d --- /dev/null +++ b/test/hotspot/jtreg/compiler/lib/ir_framework/driver/irmatching/irrule/IRRule.java @@ -0,0 +1,149 @@ +/* + * 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.lib.ir_framework.driver.irmatching.irrule; + +import compiler.lib.ir_framework.IR; +import compiler.lib.ir_framework.IRNode; +import compiler.lib.ir_framework.driver.irmatching.irmethod.IRMethod; +import compiler.lib.ir_framework.driver.irmatching.OutputMatch; +import compiler.lib.ir_framework.shared.*; + +import java.lang.reflect.Method; +import java.util.function.Consumer; + +public class IRRule { + private final IRMethod irMethod; + private final int ruleId; + private final IR irAnno; + private final FailOn failOn; + private final Counts counts; + + public IRRule(IRMethod irMethod, int ruleId, IR irAnno) { + this.irMethod = irMethod; + this.ruleId = ruleId; + this.irAnno = irAnno; + this.failOn = initFailOn(irAnno); + this.counts = initCounts(irAnno); + } + + private Counts initCounts(IR irAnno) { + String[] countsConstraints = irAnno.counts(); + if (countsConstraints.length != 0) { + try { + return Counts.create(IRNode.mergeNodes(countsConstraints), this); + } catch (TestFormatException e) { + // Logged and reported later. Continue. + } + } + return null; + } + + private FailOn initFailOn(IR irAnno) { + String[] failOnNodes = irAnno.failOn(); + if (failOnNodes.length != 0) { + return new FailOn(IRNode.mergeNodes(failOnNodes)); + } + return null; + } + + public int getRuleId() { + return ruleId; + } + + public IR getIRAnno() { + return irAnno; + } + + public Method getMethod() { + return irMethod.getMethod(); + } + + /** + * Apply this IR rule by checking any failOn and counts attributes. + */ + public IRRuleMatchResult applyCheckAttribute() { + IRRuleMatchResult result = new IRRuleMatchResult(this); + if (failOn != null) { + applyCheckAttribute(failOn, result, result::setFailOnFailures); + } + if (counts != null) { + applyCheckAttribute(counts, result, result::setCountsFailures); + } + return result; + } + + private void applyCheckAttribute(CheckAttribute checkAttribute, IRRuleMatchResult result, + Consumer setFailures) { + CheckAttributeMatchResult checkAttributeResult = checkAttribute.apply(irMethod.getOutput()); + if (checkAttributeResult.fail()) { + setFailures.accept(checkAttributeResult); + result.updateOutputMatch(getOutputMatch(checkAttribute, checkAttributeResult)); + } + } + + /** + * Determine how the output was matched by reapplying the check attribute for the PrintIdeal and PrintOptoAssembly + * output separately. + */ + private OutputMatch getOutputMatch(CheckAttribute checkAttribute, CheckAttributeMatchResult checkAttributeResult) { + int totalMatches = checkAttributeResult.getMatchesCount(); + int idealFailuresCount = getMatchesCount(checkAttribute, irMethod.getIdealOutput()); + int optoAssemblyFailuresCount = getMatchesCount(checkAttribute, irMethod.getOptoAssemblyOutput()); + return findOutputMatch(totalMatches, idealFailuresCount, optoAssemblyFailuresCount); + } + + private int getMatchesCount(CheckAttribute checkAttribute, String compilation) { + CheckAttributeMatchResult result = checkAttribute.apply(compilation); + return result.getMatchesCount(); + } + + /** + * Compare different counts to find out, on what output a failure was matched. + */ + private OutputMatch findOutputMatch(int totalMatches, int idealFailuresCount, int optoAssemblyFailuresCount) { + if (totalMatches == 0 + || someRegexMatchOnlyEntireOutput(totalMatches, idealFailuresCount, optoAssemblyFailuresCount) + || anyMatchOnIdealAndOptoAssembly(idealFailuresCount, optoAssemblyFailuresCount)) { + return OutputMatch.BOTH; + } else if (optoAssemblyFailuresCount == 0) { + return OutputMatch.IDEAL; + } else { + return OutputMatch.OPTO_ASSEMBLY; + } + } + + /** + * Do we have a regex that is only matched on the entire ideal + opto assembly output? + */ + private boolean someRegexMatchOnlyEntireOutput(int totalCount, int idealFailuresCount, int optoAssemblyFailuresCount) { + return totalCount != idealFailuresCount + optoAssemblyFailuresCount; + } + + /** + * Do we have a match on ideal and opto assembly for this rule? + */ + private boolean anyMatchOnIdealAndOptoAssembly(int idealFailuresCount, int optoAssemblyFailuresCount) { + return idealFailuresCount > 0 && optoAssemblyFailuresCount > 0; + } +} diff --git a/test/hotspot/jtreg/compiler/lib/ir_framework/driver/irmatching/irrule/IRRuleMatchResult.java b/test/hotspot/jtreg/compiler/lib/ir_framework/driver/irmatching/irrule/IRRuleMatchResult.java new file mode 100644 index 0000000000000000000000000000000000000000..c7d44498d555fdc44c5cd1c2e507226dae80c8ba --- /dev/null +++ b/test/hotspot/jtreg/compiler/lib/ir_framework/driver/irmatching/irrule/IRRuleMatchResult.java @@ -0,0 +1,102 @@ +/* + * 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.lib.ir_framework.driver.irmatching.irrule; + +import compiler.lib.ir_framework.TestFramework; +import compiler.lib.ir_framework.driver.irmatching.MatchResult; +import compiler.lib.ir_framework.driver.irmatching.OutputMatch; + +/** + * This class represents an IR matching result of an IR rule. + * + * @see CheckAttributeMatchResult + * @see IRRule + */ +public class IRRuleMatchResult implements MatchResult { + private final IRRule irRule; + private CheckAttributeMatchResult failOnFailures = null; + private CheckAttributeMatchResult countsFailures = null; + private OutputMatch outputMatch; + + public IRRuleMatchResult(IRRule irRule) { + this.irRule = irRule; + this.outputMatch = OutputMatch.NONE; + } + + private boolean hasFailOnFailures() { + return failOnFailures != null; + } + + public void setFailOnFailures(CheckAttributeMatchResult failOnFailures) { + this.failOnFailures = failOnFailures; + } + + private boolean hasCountsFailures() { + return countsFailures != null; + } + + public void setCountsFailures(CheckAttributeMatchResult countsFailures) { + this.countsFailures = countsFailures; + } + + public OutputMatch getOutputMatch() { + return outputMatch; + } + + @Override + public boolean fail() { + return failOnFailures != null || countsFailures != null; + } + + public void updateOutputMatch(OutputMatch newOutputMatch) { + TestFramework.check(newOutputMatch != OutputMatch.NONE, "must be valid state"); + switch (outputMatch) { + case NONE -> outputMatch = newOutputMatch; + case IDEAL -> outputMatch = newOutputMatch != OutputMatch.IDEAL + ? OutputMatch.BOTH : OutputMatch.IDEAL; + case OPTO_ASSEMBLY -> outputMatch = newOutputMatch != OutputMatch.OPTO_ASSEMBLY + ? OutputMatch.BOTH : OutputMatch.OPTO_ASSEMBLY; + } + } + + /** + * Build a failure message based on the collected failures of this object. + */ + @Override + public String buildFailureMessage() { + StringBuilder failMsg = new StringBuilder(); + failMsg.append(getIRRuleLine()); + if (hasFailOnFailures()) { + failMsg.append(failOnFailures.buildFailureMessage()); + } + if (hasCountsFailures()) { + failMsg.append(countsFailures.buildFailureMessage()); + } + return failMsg.toString(); + } + + private String getIRRuleLine() { + return " * @IR rule " + irRule.getRuleId() + ": \"" + irRule.getIRAnno() + "\"" + System.lineSeparator(); + } +} diff --git a/test/hotspot/jtreg/compiler/lib/ir_framework/driver/irmatching/irrule/RegexFailure.java b/test/hotspot/jtreg/compiler/lib/ir_framework/driver/irmatching/irrule/RegexFailure.java new file mode 100644 index 0000000000000000000000000000000000000000..821da618fa699d2db4a0834a5288e4835e4162f1 --- /dev/null +++ b/test/hotspot/jtreg/compiler/lib/ir_framework/driver/irmatching/irrule/RegexFailure.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. + */ + +package compiler.lib.ir_framework.driver.irmatching.irrule; + +import java.util.List; +import java.util.stream.Collectors; + +/** + * Base class representing an IR matching failure of a regex of a check attribute of an IR rule. + * + * @see CheckAttributeMatchResult + * @see CheckAttribute + * @see IRRule + */ +abstract class RegexFailure { + protected final String nodeRegex; + protected final int nodeId; + protected final List matches; + + public RegexFailure(String nodeRegex, int nodeId, List matches) { + this.nodeRegex = nodeRegex; + this.nodeId = nodeId; + this.matches = addWhiteSpacePrefixForEachLine(matches); + } + + private List addWhiteSpacePrefixForEachLine(List matches) { + return matches + .stream() + .map(s -> s.replaceAll(System.lineSeparator(), System.lineSeparator() + + getMatchedNodesItemWhiteSpace() + " ")) + .collect(Collectors.toList()); + } + + abstract public String buildFailureMessage(); + + public int getMatchesCount() { + return matches.size(); + } + + protected String getRegexLine() { + return " * Regex " + nodeId + ": " + nodeRegex + System.lineSeparator(); + } + + protected String getMatchedNodesBlock() { + return getMatchedNodesHeader() + getMatchesNodeLines(); + } + + protected String getMatchedNodesHeader() { + int matchCount = matches.size(); + return "" + getMatchedNodesWhiteSpace() + "- " + getMatchedPrefix() + " node" + + (matchCount != 1 ? "s (" + matchCount + ")" : "") + ":" + System.lineSeparator(); + } + + protected String getMatchedNodesWhiteSpace() { + return " "; + } + + abstract protected String getMatchedPrefix(); + + protected String getMatchesNodeLines() { + StringBuilder builder = new StringBuilder(); + matches.forEach(match -> builder.append(getMatchedNodesItemWhiteSpace()).append("* ").append(match).append(System.lineSeparator())); + return builder.toString(); + } + + private String getMatchedNodesItemWhiteSpace() { + return " "; + } +} diff --git a/test/jdk/sun/net/www/httptest/HttpCallback.java b/test/hotspot/jtreg/compiler/lib/ir_framework/driver/irmatching/parser/AbstractLine.java similarity index 58% rename from test/jdk/sun/net/www/httptest/HttpCallback.java rename to test/hotspot/jtreg/compiler/lib/ir_framework/driver/irmatching/parser/AbstractLine.java index 27af7b7aaf4ebbbe7cfec599d20305ec526db8ed..19bca4307099b1fa456bf8b25729cd84346c00e7 100644 --- a/test/jdk/sun/net/www/httptest/HttpCallback.java +++ b/test/hotspot/jtreg/compiler/lib/ir_framework/driver/irmatching/parser/AbstractLine.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 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,19 +21,31 @@ * questions. */ +package compiler.lib.ir_framework.driver.irmatching.parser; + +import java.io.BufferedReader; +import java.io.IOException; + /** - * This interface is implemented by classes that wish to handle incoming HTTP - * requests and generate responses. This could be a general purpose HTTP server - * or a test case that expects specific requests from a client. - *

- * The incoming request fields can be examined via the {@link HttpTransaction} - * object, and a response can also be generated and sent via the request object. + * Base class of a read line from the hotspot_pid* file. */ -public interface HttpCallback { +abstract class AbstractLine { + private final BufferedReader reader; + protected String line; + + public AbstractLine(BufferedReader reader) { + this.reader = reader; + } + + public String getLine() { + return line; + } + /** - * handle the given request and generate an appropriate response. - * @param msg the transaction containing the request from the - * client and used to send the response + * Read next line and return it. If we've reached the end of the file, return NULL instead. */ - void request (HttpTransaction msg); + public boolean readLine() throws IOException { + line = reader.readLine(); + return line != null; + } } diff --git a/test/hotspot/jtreg/compiler/lib/ir_framework/driver/irmatching/parser/BlockLine.java b/test/hotspot/jtreg/compiler/lib/ir_framework/driver/irmatching/parser/BlockLine.java new file mode 100644 index 0000000000000000000000000000000000000000..0fa91a43c5ed631757327f4d258a5306fd3e178e --- /dev/null +++ b/test/hotspot/jtreg/compiler/lib/ir_framework/driver/irmatching/parser/BlockLine.java @@ -0,0 +1,43 @@ +/* + * 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.lib.ir_framework.driver.irmatching.parser; + +import java.io.BufferedReader; + +/** + * Class representing a block line inside a PrintIdeal or PrintOptoAssembly output block read from the hotspot_pid* file. + */ +class BlockLine extends AbstractLine { + + public BlockLine(BufferedReader reader) { + super(reader); + } + + /** + * Is this line an end of a PrintIdeal or PrintOptoAssembly output block? + */ + public boolean isBlockEnd() { + return line.startsWith(""); + line = line.replace(""", "\""); + line = line.replace("'", "'"); + line = line.replace("&", "&"); + } + return line; + } +} diff --git a/test/hotspot/jtreg/compiler/lib/ir_framework/driver/irmatching/parser/FileCorruptedException.java b/test/hotspot/jtreg/compiler/lib/ir_framework/driver/irmatching/parser/FileCorruptedException.java new file mode 100644 index 0000000000000000000000000000000000000000..5681eb662ee99ae6b098bf63ed2dc6074f800f65 --- /dev/null +++ b/test/hotspot/jtreg/compiler/lib/ir_framework/driver/irmatching/parser/FileCorruptedException.java @@ -0,0 +1,33 @@ +/* + * 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.lib.ir_framework.driver.irmatching.parser; + +/** + * Exception thrown when facing an unexpected format during parsing of the hotspot-pid* file + */ +class FileCorruptedException extends RuntimeException { + public FileCorruptedException(String s) { + super(s); + } +} diff --git a/test/hotspot/jtreg/compiler/lib/ir_framework/driver/irmatching/parser/HotSpotPidFileParser.java b/test/hotspot/jtreg/compiler/lib/ir_framework/driver/irmatching/parser/HotSpotPidFileParser.java new file mode 100644 index 0000000000000000000000000000000000000000..2e5a1d334561c81b1075b303e61b7dcc1c41325e --- /dev/null +++ b/test/hotspot/jtreg/compiler/lib/ir_framework/driver/irmatching/parser/HotSpotPidFileParser.java @@ -0,0 +1,142 @@ +/* + * 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.lib.ir_framework.driver.irmatching.parser; + +import compiler.lib.ir_framework.TestFramework; +import compiler.lib.ir_framework.driver.irmatching.irmethod.IRMethod; +import compiler.lib.ir_framework.shared.TestFrameworkException; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * Class to parse the PrintIdeal and PrintOptoAssembly outputs of the test class from the hotspot_pid* file and add them + * to the collection of {@link IRMethod} created by {@link IREncodingParser}. + * + * @see IRMethod + * @see IREncodingParser + */ +class HotSpotPidFileParser { + private static final Pattern COMPILE_ID_PATTERN = Pattern.compile("compile_id='(\\d+)'"); + + private final Pattern compileIdPatternForTestClass; + private Map compilationsMap; + + public HotSpotPidFileParser(String testClass) { + this.compileIdPatternForTestClass = Pattern.compile("compile_id='(\\d+)'.*" + Pattern.quote(testClass) + " (\\S+)"); + } + + public void setCompilationsMap(Map compilationsMap) { + this.compilationsMap = compilationsMap; + } + /** + * Parse the hotspot_pid*.log file from the test VM. Read the PrintIdeal and PrintOptoAssembly outputs for all + * methods of the test class that need to be IR matched (found in compilations map). + */ + public Collection parseCompilations(String hotspotPidFileName) { + try { + processFileLines(hotspotPidFileName); + return compilationsMap.values(); + } catch (IOException e) { + throw new TestFrameworkException("Error while reading " + hotspotPidFileName, e); + } catch (FileCorruptedException e) { + throw new TestFrameworkException("Unexpected format of " + hotspotPidFileName, e); + } + } + + private void processFileLines(String hotspotPidFileName) throws IOException { + Map compileIdMap = new HashMap<>(); + try (var reader = Files.newBufferedReader(Paths.get(hotspotPidFileName))) { + Line line = new Line(reader, compileIdPatternForTestClass); + BlockOutputReader blockOutputReader = new BlockOutputReader(reader); + while (line.readLine()) { + if (line.isTestClassCompilation()) { + parseTestMethodCompileId(compileIdMap, line.getLine()); + } else if (isTestMethodBlockStart(line, compileIdMap)) { + String blockOutput = blockOutputReader.readBlock(); + setIRMethodOutput(blockOutput, line, compileIdMap); + } + } + } + } + + private void parseTestMethodCompileId(Map compileIdMap, String line) { + String methodName = parseMethodName(line); + if (isTestAnnotatedMethod(methodName)) { + int compileId = getCompileId(line); + compileIdMap.put(compileId, getIrMethod(methodName)); + } + } + + private String parseMethodName(String line) { + Matcher matcher = compileIdPatternForTestClass.matcher(line); + TestFramework.check(matcher.find(), "must find match"); + return matcher.group(2); + } + + private boolean isTestAnnotatedMethod(String testMethodName) { + return compilationsMap.containsKey(testMethodName); + } + + private IRMethod getIrMethod(String testMethodName) { + return compilationsMap.get(testMethodName); + } + + + + private int getCompileId(String line) { + Matcher matcher = COMPILE_ID_PATTERN.matcher(line); + if (!matcher.find()) { + throw new FileCorruptedException("Unexpected format found on this line: " + line); + } + return Integer.parseInt(matcher.group(1)); + } + + private boolean isTestMethodBlockStart(Line line, Map compileIdMap) { + return line.isBlockStart() && isTestClassMethodBlock(line, compileIdMap); + } + + private boolean isTestClassMethodBlock(Line line, Map compileIdMap) { + return compileIdMap.containsKey(getCompileId(line.getLine())); + } + + public void setIRMethodOutput(String blockOutput, Line blockStartLine, Map compileIdMap) { + IRMethod irMethod = compileIdMap.get(getCompileId(blockStartLine.getLine())); + setIRMethodOutput(blockOutput, blockStartLine, irMethod); + } + + private void setIRMethodOutput(String blockOutput, Line blockStartLine, IRMethod irMethod) { + if (blockStartLine.isPrintIdealStart()) { + irMethod.setIdealOutput(blockOutput); + } else { + irMethod.setOptoAssemblyOutput(blockOutput); + } + } +} diff --git a/test/hotspot/jtreg/compiler/lib/ir_framework/driver/irmatching/parser/IREncodingParser.java b/test/hotspot/jtreg/compiler/lib/ir_framework/driver/irmatching/parser/IREncodingParser.java new file mode 100644 index 0000000000000000000000000000000000000000..5e539a25962dfbbe1417f2c6e89e4f87b5ed88e8 --- /dev/null +++ b/test/hotspot/jtreg/compiler/lib/ir_framework/driver/irmatching/parser/IREncodingParser.java @@ -0,0 +1,153 @@ +/* + * 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.lib.ir_framework.driver.irmatching.parser; + +import compiler.lib.ir_framework.IR; +import compiler.lib.ir_framework.TestFramework; +import compiler.lib.ir_framework.driver.irmatching.irmethod.IRMethod; +import compiler.lib.ir_framework.shared.TestFormat; +import compiler.lib.ir_framework.shared.TestFrameworkException; +import compiler.lib.ir_framework.test.IREncodingPrinter; + +import java.lang.reflect.Method; +import java.util.HashMap; +import java.util.Map; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * Class to parse the IR encoding emitted by the test VM and creating {@link IRMethod} objects for each entry. + * + * @see IRMethod + */ +class IREncodingParser { + + private static final boolean PRINT_IR_ENCODING = Boolean.parseBoolean(System.getProperty("PrintIREncoding", "false")); + private static final Pattern IR_ENCODING_PATTERN = + Pattern.compile("(?<=" + IREncodingPrinter.START + "\r?\n).*\\R([\\s\\S]*)(?=" + IREncodingPrinter.END + ")"); + + private final Map compilations; + private final Class testClass; + + public IREncodingParser(Class testClass) { + this.testClass = testClass; + this.compilations = new HashMap<>(); + } + + public Map parseIRMethods(String irEncoding) { + if (TestFramework.VERBOSE || PRINT_IR_ENCODING) { + System.out.println("Read IR encoding from test VM:"); + System.out.println(irEncoding); + } + createCompilationsMap(irEncoding, testClass); + // We could have found format errors in @IR annotations. Report them now with an exception. + TestFormat.throwIfAnyFailures(); + return compilations; + } + + /** + * Sets up a map testname -> IRMethod (containing the PrintIdeal and PrintOptoAssembly output for testname). + */ + private void createCompilationsMap(String irEncoding, Class testClass) { + Map irRulesMap = parseIREncoding(irEncoding); + createIRMethodsWithEncoding(testClass, irRulesMap); + } + + /** + * Read the IR encoding emitted by the test VM to decide if an @IR rule must be checked for a method. + */ + private Map parseIREncoding(String irEncoding) { + Map irRulesMap = new HashMap<>(); + String[] irEncodingLines = getIREncodingLines(irEncoding); + for (String s : irEncodingLines) { + String line = s.trim(); + String[] splitLine = line.split(","); + if (splitLine.length < 2) { + throw new TestFrameworkException("Invalid IR match rule encoding. No comma found: " + splitLine[0]); + } + String testName = splitLine[0]; + int[] irRulesIdx = getRuleIndexes(splitLine); + irRulesMap.put(testName, irRulesIdx); + } + return irRulesMap; + } + + /** + * Parse the IR encoding lines without header, explanation line and footer and return them in an array. + */ + private String[] getIREncodingLines(String irEncoding) { + Matcher matcher = IR_ENCODING_PATTERN.matcher(irEncoding); + TestFramework.check(matcher.find(), "Did not find IR encoding"); + String lines = matcher.group(1).trim(); + if (lines.isEmpty()) { + // Nothing to IR match. + return new String[0]; + } + return lines.split("\\R"); + } + + /** + * Parse rule indexes from IR encoding line of the format: + */ + private int[] getRuleIndexes(String[] splitLine) { + int[] irRulesIdx = new int[splitLine.length - 1]; + for (int i = 1; i < splitLine.length; i++) { + try { + irRulesIdx[i - 1] = Integer.parseInt(splitLine[i]); + } catch (NumberFormatException e) { + throw new TestFrameworkException("Invalid IR match rule encoding. No number found: " + splitLine[i]); + } + } + return irRulesIdx; + } + + private void createIRMethodsWithEncoding(Class testClass, Map irRulesMap) { + for (Method m : testClass.getDeclaredMethods()) { + IR[] irAnnos = m.getAnnotationsByType(IR.class); + if (irAnnos.length > 0) { + // Validation of legal @IR attributes and placement of the annotation was already done in Test VM. + int[] irRuleIds = irRulesMap.get(m.getName()); + validateIRRuleIds(m, irAnnos, irRuleIds); + if (hasAnyApplicableIRRules(irRuleIds)) { + compilations.put(m.getName(), new IRMethod(m, irRuleIds, irAnnos)); + } + } + } + } + + private void validateIRRuleIds(Method m, IR[] irAnnos, int[] ids) { + TestFramework.check(ids != null, "Should find method name in validIrRulesMap for " + m); + TestFramework.check(ids.length > 0, "Did not find any rule indices for " + m); + TestFramework.check((ids[0] >= 1 || ids[0] == IREncodingPrinter.NO_RULE_APPLIED) + && ids[ids.length - 1] <= irAnnos.length, + "Invalid IR rule index found in validIrRulesMap for " + m); + } + + /** + * Does the list of IR rules contain any applicable IR rules for the given conditions? + */ + private boolean hasAnyApplicableIRRules(int[] irRuleIds) { + return irRuleIds[0] != IREncodingPrinter.NO_RULE_APPLIED; + } +} diff --git a/test/hotspot/jtreg/compiler/lib/ir_framework/driver/irmatching/parser/IRMethodParser.java b/test/hotspot/jtreg/compiler/lib/ir_framework/driver/irmatching/parser/IRMethodParser.java new file mode 100644 index 0000000000000000000000000000000000000000..332b88d96c6b87e9577205c33b997ee69223a6e8 --- /dev/null +++ b/test/hotspot/jtreg/compiler/lib/ir_framework/driver/irmatching/parser/IRMethodParser.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. + */ + +package compiler.lib.ir_framework.driver.irmatching.parser; + +import compiler.lib.ir_framework.driver.irmatching.irmethod.IRMethod; + +import java.util.Collection; +import java.util.Map; + +/** + * Class to parse the PrintIdeal and PrintOptoAssembly outputs of the test class and store them into a collection + * of dedicated IRMethod objects used throughout IR matching. + * + * @see IRMethod + */ +public class IRMethodParser { + private final IREncodingParser irEncodingParser; + private final HotSpotPidFileParser hotSpotPidFileParser; + + public IRMethodParser(Class testClass) { + this.irEncodingParser = new IREncodingParser(testClass); + this.hotSpotPidFileParser = new HotSpotPidFileParser(testClass.getName()); + } + + /** + * Parse the IR encoding and hotspot_pid* file to create a collection of {@link IRMethod} objects. + * Return null if there are no applicable @IR rules in any method of the test class. + */ + public Collection parse(String hotspotPidFileName, String irEncoding) { + Map compilationsMap = irEncodingParser.parseIRMethods(irEncoding); + if (!compilationsMap.isEmpty()) { + hotSpotPidFileParser.setCompilationsMap(compilationsMap); + return hotSpotPidFileParser.parseCompilations(hotspotPidFileName); + } + return null; + } +} diff --git a/test/hotspot/jtreg/compiler/lib/ir_framework/driver/irmatching/parser/Line.java b/test/hotspot/jtreg/compiler/lib/ir_framework/driver/irmatching/parser/Line.java new file mode 100644 index 0000000000000000000000000000000000000000..16ef31b719d9c5c193cf5bba5d4f7896e6688f20 --- /dev/null +++ b/test/hotspot/jtreg/compiler/lib/ir_framework/driver/irmatching/parser/Line.java @@ -0,0 +1,97 @@ +/* + * 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.lib.ir_framework.driver.irmatching.parser; + +import java.io.BufferedReader; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * Class representing a normal line read from the hotspot_pid* file. + */ +class Line extends AbstractLine { + private final Pattern compileIdPatternForTestClass; + + public Line(BufferedReader reader, Pattern compileIdPatternForTestClass) { + super(reader); + this.compileIdPatternForTestClass = compileIdPatternForTestClass; + } + + /** + * Is this line a start of a @Test annotated method? We only care about test class entries. There might be non-class + * entries as well if user specified additional compile commands. Ignore these. + */ + public boolean isTestClassCompilation() { + if (isCompilation()) { + Matcher matcher = compileIdPatternForTestClass.matcher(line); + return matcher.find(); + } + return false; + } + + /** + * Is this header a C2 non-OSR compilation header entry? + */ + public boolean isCompilation() { + return line.startsWith("> { + private final T givenValue; // Right hand side + private final BiPredicate comparisonPredicate; + private final String comparator; + + public Comparison(T givenValue, String comparator, BiPredicate comparisonPredicate) { + this.givenValue = givenValue; + this.comparator = comparator; + this.comparisonPredicate = comparisonPredicate; + } + + public T getGivenValue() { + return givenValue; + } + + public String getComparator() { + return comparator; + } + + /** + * Comparison: foundValue OP givenValue + */ + public boolean compare(T foundValue) { + return comparisonPredicate.test(foundValue, givenValue); + } +} diff --git a/test/hotspot/jtreg/compiler/lib/ir_framework/shared/ComparisonConstraintParser.java b/test/hotspot/jtreg/compiler/lib/ir_framework/shared/ComparisonConstraintParser.java new file mode 100644 index 0000000000000000000000000000000000000000..4848a32859fc47e0e7f8f0d0fb88638c05541069 --- /dev/null +++ b/test/hotspot/jtreg/compiler/lib/ir_framework/shared/ComparisonConstraintParser.java @@ -0,0 +1,150 @@ +/* + * 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 compiler.lib.ir_framework.shared; + +import java.util.function.BiPredicate; +import java.util.function.Function; + +/** + * Utility class to parse a comparator either in the applyIf* or in the counts properties of an @IR rules. + */ +public class ComparisonConstraintParser> { + + private enum Comparator { + ONE_CHAR, TWO_CHARS + } + + public static > Comparison parse(String constraint, Function parseFunction, + String postfixErrorMsg) { + try { + return parseConstraintAndValue(constraint, parseFunction); + } catch (EmptyConstraintException e) { + TestFormat.fail("Provided empty value " + postfixErrorMsg); + throw new UnreachableCodeException(); + } catch (MissingConstraintValueException e) { + TestFormat.fail("Provided empty value after comparator \"" + e.getComparator() + "\" " + postfixErrorMsg); + throw new UnreachableCodeException(); + } catch (InvalidComparatorException e) { + TestFormat.fail("Provided invalid comparator \"" + e.getComparator() + "\" " + postfixErrorMsg); + throw new UnreachableCodeException(); + } catch (InvalidConstraintValueException e) { + String comparator = e.getComparator(); + if (!comparator.isEmpty()) { + comparator = " after comparator \"" + comparator + "\""; + } + TestFormat.fail("Provided invalid value \"" + e.getInvalidValue() + "\"" + + comparator + " " + postfixErrorMsg); + throw new UnreachableCodeException(); + } + } + + private static > Comparison parseConstraintAndValue(String constraint, + Function parseFunction) throws + EmptyConstraintException, MissingConstraintValueException, + InvalidComparatorException, InvalidConstraintValueException { + ParsedResult result = parse(constraint); + T givenValue = parseGivenValue(parseFunction, result); + return new Comparison<>(givenValue, result.comparator, result.comparisonPredicate); + } + + private static > ParsedResult parse(String constraint) throws + EmptyConstraintException, MissingConstraintValueException, InvalidComparatorException { + constraint = constraint.trim(); + if (constraint.isEmpty()) { + throw new EmptyConstraintException(); + } + switch (constraint.charAt(0)) { + case '<' -> { + throwIfNoValueAfterComparator(constraint, Comparator.ONE_CHAR); + if (constraint.charAt(1) == '=') { + throwIfNoValueAfterComparator(constraint, Comparator.TWO_CHARS); + return new ParsedResult<>(constraint.substring(2).trim(), "<=", (x, y) -> x.compareTo(y) <= 0); + } else { + return new ParsedResult<>(constraint.substring(1).trim(), "<", (x, y) -> x.compareTo(y) < 0); + } + } + case '>' -> { + throwIfNoValueAfterComparator(constraint, Comparator.ONE_CHAR); + if (constraint.charAt(1) == '=') { + throwIfNoValueAfterComparator(constraint, Comparator.TWO_CHARS); + return new ParsedResult<>(constraint.substring(2).trim(), ">=", (x, y) -> x.compareTo(y) >= 0); + } else { + return new ParsedResult<>(constraint.substring(1).trim(), ">", (x, y) -> x.compareTo(y) > 0); + } + } + case '!' -> { + throwIfNoValueAfterComparator(constraint, Comparator.ONE_CHAR); + if (constraint.charAt(1) != '=') { + throw new InvalidComparatorException("!"); + } + throwIfNoValueAfterComparator(constraint, Comparator.TWO_CHARS); + return new ParsedResult<>(constraint.substring(2).trim(), "!=", (x, y) -> x.compareTo(y) != 0); + } + case '=' -> { // Allowed syntax, equivalent to not using any symbol. + throwIfNoValueAfterComparator(constraint, Comparator.ONE_CHAR); + return new ParsedResult<>(constraint.substring(1).trim(), "=", (x, y) -> x.compareTo(y) == 0); + } + default -> { + return new ParsedResult<>(constraint.trim(), "=", (x, y) -> x.compareTo(y) == 0); + } + } + } + + private static void throwIfNoValueAfterComparator(String constraint, Comparator comparator) throws MissingConstraintValueException { + switch (comparator) { + case ONE_CHAR -> { + if (constraint.length() == 1) { + throw new MissingConstraintValueException(constraint); + } + } + case TWO_CHARS -> { + if (constraint.length() == 2) { + throw new MissingConstraintValueException(constraint); + } + } + } + } + + private static > T parseGivenValue(Function parseFunction, ParsedResult result) + throws InvalidConstraintValueException { + try { + return parseFunction.apply(result.value); + } + catch (NumberFormatException e) { + throw new InvalidConstraintValueException(result.value, result.comparator); + } + } + + static class ParsedResult { + public String value; + public BiPredicate comparisonPredicate; + public String comparator; + + public ParsedResult(String value, String comparator,BiPredicate comparisonPredicate) { + this.value = value; + this.comparator = comparator; + this.comparisonPredicate = comparisonPredicate; + } + } +} diff --git a/test/hotspot/jtreg/compiler/lib/ir_framework/shared/EmptyConstraintException.java b/test/hotspot/jtreg/compiler/lib/ir_framework/shared/EmptyConstraintException.java new file mode 100644 index 0000000000000000000000000000000000000000..6dfd31819ee13fc4b6afdfd6bd61df00ccaa47ac --- /dev/null +++ b/test/hotspot/jtreg/compiler/lib/ir_framework/shared/EmptyConstraintException.java @@ -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. + * + * 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.lib.ir_framework.shared; + +/** + * Exception thrown when {@link ComparisonConstraintParser} cannot find a constraint. + */ +class EmptyConstraintException extends Exception { +} diff --git a/test/hotspot/jtreg/compiler/lib/ir_framework/shared/InvalidComparatorException.java b/test/hotspot/jtreg/compiler/lib/ir_framework/shared/InvalidComparatorException.java new file mode 100644 index 0000000000000000000000000000000000000000..4ab550e8be899dadb5643b57b0582b939be07d42 --- /dev/null +++ b/test/hotspot/jtreg/compiler/lib/ir_framework/shared/InvalidComparatorException.java @@ -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. + */ + +package compiler.lib.ir_framework.shared; + +/** + * Exception threw when {@link ComparisonConstraintParser} parses an invalid comparator. + */ +public class InvalidComparatorException extends Exception { + private final String comparator; + + public InvalidComparatorException(String comparator) { + this.comparator = comparator; + } + + public String getComparator() { + return comparator; + } +} diff --git a/test/hotspot/jtreg/compiler/lib/ir_framework/shared/InvalidConstraintValueException.java b/test/hotspot/jtreg/compiler/lib/ir_framework/shared/InvalidConstraintValueException.java new file mode 100644 index 0000000000000000000000000000000000000000..a415ebf404645148482c61f4c23fea0112a3d49c --- /dev/null +++ b/test/hotspot/jtreg/compiler/lib/ir_framework/shared/InvalidConstraintValueException.java @@ -0,0 +1,45 @@ +/* + * 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.lib.ir_framework.shared; + +/** + * Exception thrown when {@link ComparisonConstraintParser} parses an invalid value. + */ +class InvalidConstraintValueException extends Exception { + private final String invalidValue; + private final String comparator; + + public InvalidConstraintValueException(String invalidValue, String comparator) { + this.invalidValue = invalidValue; + this.comparator = comparator; + } + + public String getInvalidValue() { + return invalidValue; + } + + public String getComparator() { + return comparator; + } +} diff --git a/test/hotspot/jtreg/compiler/lib/ir_framework/shared/MissingConstraintValueException.java b/test/hotspot/jtreg/compiler/lib/ir_framework/shared/MissingConstraintValueException.java new file mode 100644 index 0000000000000000000000000000000000000000..12230f9219c2e04b245ad4387e7555ae60fdfd73 --- /dev/null +++ b/test/hotspot/jtreg/compiler/lib/ir_framework/shared/MissingConstraintValueException.java @@ -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. + */ + +package compiler.lib.ir_framework.shared; + +/** + * Exception thrown when {@link ComparisonConstraintParser} cannot find a value in a constraint after a comparator. + */ +class MissingConstraintValueException extends Exception { + private final String comparator; + + public MissingConstraintValueException(String comparator) { + this.comparator = comparator; + } + + public String getComparator() { + return comparator; + } +} diff --git a/test/hotspot/jtreg/compiler/lib/ir_framework/shared/ParsedComparator.java b/test/hotspot/jtreg/compiler/lib/ir_framework/shared/ParsedComparator.java deleted file mode 100644 index 9d574bc50a4ac26f60aac91a34cab7aa78260cef..0000000000000000000000000000000000000000 --- a/test/hotspot/jtreg/compiler/lib/ir_framework/shared/ParsedComparator.java +++ /dev/null @@ -1,104 +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. - */ - -package compiler.lib.ir_framework.shared; - -import java.util.function.BiPredicate; - -/** - * Utility class to parse a comparator either in the applyIf* or in the counts properties of an @IR rules. - */ -public class ParsedComparator> { - private final String strippedString; - private final BiPredicate predicate; - private final String comparator; - - public ParsedComparator(String strippedString, BiPredicate predicate, String comparator) { - this.strippedString = strippedString; - this.predicate = predicate; - this.comparator = comparator; - } - - public String getStrippedString() { - return strippedString; - } - - public BiPredicate getPredicate() { - return predicate; - } - - public String getComparator() { - return comparator; - } - - /** - * Return parsed comparator object which provides the predicate to perform the test. - * Allowed comparators: <, <=, >, =>, =, != - */ - public static > ParsedComparator parseComparator(String value) throws CheckedTestFrameworkException { - BiPredicate comparison; - value = value.trim(); - String comparator = ""; - switch (value.charAt(0)) { - case '<': - if (value.charAt(1) == '=') { - comparator = "<="; - comparison = (x, y) -> x.compareTo(y) <= 0; - value = value.substring(2).trim(); - } else { - comparator = "<"; - comparison = (x, y) -> x.compareTo(y) < 0; - value = value.substring(1).trim(); - } - break; - case '>': - if (value.charAt(1) == '=') { - comparator = ">="; - comparison = (x, y) -> x.compareTo(y) >= 0; - value = value.substring(2).trim(); - } else { - comparator = ">"; - comparison = (x, y) -> x.compareTo(y) > 0; - value = value.substring(1).trim(); - } - break; - case '!': - if (value.charAt(1) != '=') { - throw new CheckedTestFrameworkException(value.substring(0, 1)); - } - comparator = "!="; - comparison = (x, y) -> x.compareTo(y) != 0; - value = value.substring(2).trim(); - break; - case '=': // Allowed syntax, equivalent to not using any symbol. - comparator = "="; - value = value.substring(1).trim(); - // Fall through - default: - comparison = (x, y) -> x.compareTo(y) == 0; - value = value.trim(); - break; - } - return new ParsedComparator<>(value, comparison, comparator); - } -} diff --git a/test/hotspot/jtreg/compiler/lib/ir_framework/shared/TestFormat.java b/test/hotspot/jtreg/compiler/lib/ir_framework/shared/TestFormat.java index 624753fee2faac5c41dc3c434e2be87932f79331..d7a93228a6b74e8e0e72edbfd0532fe23013275b 100644 --- a/test/hotspot/jtreg/compiler/lib/ir_framework/shared/TestFormat.java +++ b/test/hotspot/jtreg/compiler/lib/ir_framework/shared/TestFormat.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,7 +53,7 @@ public class TestFormat { FAILURES.add(failureMessage); } - public static void reportIfAnyFailures() { + public static void throwIfAnyFailures() { if (FAILURES.isEmpty()) { // No format violation detected. return; diff --git a/test/hotspot/jtreg/compiler/lib/ir_framework/shared/UnreachableCodeException.java b/test/hotspot/jtreg/compiler/lib/ir_framework/shared/UnreachableCodeException.java new file mode 100644 index 0000000000000000000000000000000000000000..274b05dd32357aee8924b0f83938fdf477168338 --- /dev/null +++ b/test/hotspot/jtreg/compiler/lib/ir_framework/shared/UnreachableCodeException.java @@ -0,0 +1,36 @@ +/* + * 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.lib.ir_framework.shared; + +/** + * The error reporting of the IR framework is throwing exceptions unconditionally in separate methods. The calling methods, + * however, do not see these exceptions. As a result, Java and/or some IDEs could complain about impossible states + * (e.g. uninitialized variables, null pointer dereferences etc. even though an exception will be thrown earlier). + * To avoid that, throw an instance of this class instead. + */ +class UnreachableCodeException extends RuntimeException { + public UnreachableCodeException() { + super("Unreachable code"); + } +} diff --git a/test/hotspot/jtreg/compiler/lib/ir_framework/test/IREncodingPrinter.java b/test/hotspot/jtreg/compiler/lib/ir_framework/test/IREncodingPrinter.java index dc3a2d304eb3f7588554a80cc84c8224264dfe5b..5f7438a36daa2e600c0453f3b504e1582a3d4968 100644 --- a/test/hotspot/jtreg/compiler/lib/ir_framework/test/IREncodingPrinter.java +++ b/test/hotspot/jtreg/compiler/lib/ir_framework/test/IREncodingPrinter.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 @@ -37,7 +37,7 @@ import java.util.function.Function; /** * Prints an encoding to the dedicated test framework socket whether @IR rules of @Test methods should be applied or not. * This is done during the execution of the test VM by checking the active VM flags. This encoding is eventually parsed - * and checked by the IRMatcher class in the driver VM after the termination of the test VM. + * and checked by the IRMatcher class in the driver VM after the termination of the test VM. IR rule indices start at 1. */ public class IREncodingPrinter { public static final String START = "##### IRMatchRulesEncoding - used by TestFramework #####"; @@ -73,7 +73,7 @@ public class IREncodingPrinter { ruleIndex = i + 1; try { if (shouldApplyIrRule(irAnno)) { - validRules.add(i); + validRules.add(ruleIndex); } } catch (TestFormatException e) { // Catch logged failure and continue to check other IR annotations. @@ -206,11 +206,11 @@ public class IREncodingPrinter { } actualFlagValue = LONG_GETTERS.stream().map(f -> f.apply(flag)).filter(Objects::nonNull).findAny().orElse(null); if (actualFlagValue != null) { - return checkLongFlag(flag, value, (Long) actualFlagValue); + return checkFlag(Long::parseLong, "integer", flag, value, (Long) actualFlagValue); } actualFlagValue = WHITE_BOX.getDoubleVMFlag(flag); if (actualFlagValue != null) { - return checkDoubleFlag(flag, value, (Double) actualFlagValue); + return checkFlag(Double::parseDouble, "floating point", flag, value, (Double) actualFlagValue); } actualFlagValue = WHITE_BOX.getStringVMFlag(flag); if (actualFlagValue != null) { @@ -242,60 +242,20 @@ public class IREncodingPrinter { return booleanValue == actualFlagValue; } - private boolean checkLongFlag(String flag, String value, long actualFlagValue) { - long longValue; - ParsedComparator parsedComparator; + private > boolean checkFlag(Function parseFunction, String kind, String flag, + String value, T actualFlagValue) { try { - parsedComparator = ParsedComparator.parseComparator(value); - } catch (CheckedTestFrameworkException e) { - TestFormat.failNoThrow("Invalid comparator in \"" + value + "\" for integer based flag " + flag + failAt()); - return false; - } catch (IndexOutOfBoundsException e) { - TestFormat.failNoThrow("Provided empty value for integer based flag " + flag + failAt()); - return false; - } - try { - longValue = Long.parseLong(parsedComparator.getStrippedString()); - } catch (NumberFormatException e) { - String comparator = parsedComparator.getComparator(); - if (!comparator.isEmpty()) { - comparator = "after comparator \"" + parsedComparator.getComparator() + "\""; - } - TestFormat.failNoThrow("Invalid value \"" + parsedComparator.getStrippedString() + "\" " - + comparator + " for integer based flag " + flag + failAt()); - return false; - } - return parsedComparator.getPredicate().test(actualFlagValue, longValue); - } - - private boolean checkDoubleFlag(String flag, String value, double actualFlagValue) { - double doubleValue; - ParsedComparator parsedComparator; - try { - parsedComparator = ParsedComparator.parseComparator(value); - } catch (CheckedTestFrameworkException e) { - TestFormat.failNoThrow("Invalid comparator in \"" + value + "\" for floating point based flag " + flag + failAt()); - return false; - } catch (IndexOutOfBoundsException e) { - TestFormat.failNoThrow("Provided empty value for floating point based flag " + flag + failAt()); - return false; - } - try { - doubleValue = Double.parseDouble(parsedComparator.getStrippedString()); - } catch (NumberFormatException e) { - String comparator = parsedComparator.getComparator(); - if (!comparator.isEmpty()) { - comparator = "after comparator \"" + parsedComparator.getComparator() + "\""; - } - TestFormat.failNoThrow("Invalid value \"" + parsedComparator.getStrippedString() + "\" " - + comparator + " for floating point based flag " + flag + failAt()); + String postFixErrorMsg = "for " + kind + " based flag \"" + flag + "\"" + failAt(); + Comparison comparison = ComparisonConstraintParser.parse(value, parseFunction, postFixErrorMsg); + return comparison.compare(actualFlagValue); + } catch (TestFormatException e) { + // Format exception, do not apply rule. return false; } - return parsedComparator.getPredicate().test(actualFlagValue, doubleValue); } private String failAt() { - return " for @IR rule " + ruleIndex + " at " + method; + return " in @IR rule " + ruleIndex + " at " + method; } public void emit() { diff --git a/test/hotspot/jtreg/compiler/lib/ir_framework/test/TestVM.java b/test/hotspot/jtreg/compiler/lib/ir_framework/test/TestVM.java index 0ed89a1f633730a42343b72de34eb3369c33ef12..6a35b27cd44051b364057015347d52d8e9e37557 100644 --- a/test/hotspot/jtreg/compiler/lib/ir_framework/test/TestVM.java +++ b/test/hotspot/jtreg/compiler/lib/ir_framework/test/TestVM.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 @@ -267,7 +267,7 @@ public class TestVM { if (PRINT_VALID_IR_RULES) { irMatchRulePrinter.emit(); } - TestFormat.reportIfAnyFailures(); + TestFormat.throwIfAnyFailures(); declaredTests.clear(); testMethodMap.clear(); } diff --git a/test/hotspot/jtreg/compiler/patches/java.base/java/lang/Helper.java b/test/hotspot/jtreg/compiler/patches/java.base/java/lang/Helper.java index ded4a58945d09e2337bbea37a0a416445b77377a..6d8b5be79bf84a30556901c98bf53768fd285fd6 100644 --- a/test/hotspot/jtreg/compiler/patches/java.base/java/lang/Helper.java +++ b/test/hotspot/jtreg/compiler/patches/java.base/java/lang/Helper.java @@ -32,6 +32,11 @@ public class Helper { return StringCoding.hasNegatives(ba, off, len); } + @jdk.internal.vm.annotation.ForceInline + public static int StringCodingCountPositives(byte[] ba, int off, int len) { + return StringCoding.countPositives(ba, off, len); + } + @jdk.internal.vm.annotation.ForceInline public static byte[] compressByte(byte[] src, int srcOff, int dstSize, int dstOff, int len) { byte[] dst = new byte[dstSize]; diff --git a/test/hotspot/jtreg/compiler/print/PrintInlining.java b/test/hotspot/jtreg/compiler/print/PrintInlining.java index deb1ae0aae0791be7a5202e10fafeae60d9945f8..4b45a32949f5773f46d2dca26a67da557403e243 100644 --- a/test/hotspot/jtreg/compiler/print/PrintInlining.java +++ b/test/hotspot/jtreg/compiler/print/PrintInlining.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 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,11 +23,14 @@ /* * @test - * @bug 8022585 + * @bug 8022585 8277055 * @summary VM crashes when ran with -XX:+PrintInlining * @run main/othervm -Xcomp -XX:+UnlockDiagnosticVMOptions -XX:+PrintInlining * compiler.print.PrintInlining - * + * @run main/othervm -Xcomp -XX:-TieredCompilation -XX:+UnlockDiagnosticVMOptions -XX:+PrintInlining + * compiler.print.PrintInlining + * @run main/othervm -Xcomp -XX:-TieredCompilation -XX:+UnlockDiagnosticVMOptions -XX:+PrintIntrinsics + * compiler.print.PrintInlining */ package compiler.print; diff --git a/test/hotspot/jtreg/compiler/rangechecks/TestLongRangeCheck.java b/test/hotspot/jtreg/compiler/rangechecks/TestLongRangeCheck.java index d56d19278cfb84e435f6a41933fc8cc7095a8c2a..1cd04523ba7c6d7be475957dd641d764cfd12f07 100644 --- a/test/hotspot/jtreg/compiler/rangechecks/TestLongRangeCheck.java +++ b/test/hotspot/jtreg/compiler/rangechecks/TestLongRangeCheck.java @@ -127,6 +127,73 @@ public class TestLongRangeCheck { assertIsNotCompiled(m); } + private static void testOverflow(String method, long start, long stop, long length, long offset0, long offset1) throws Exception { + Method m = newClassLoader().loadClass("TestLongRangeCheck").getDeclaredMethod(method, long.class, long.class, long.class, long.class); + m.invoke(null, start, stop, length, offset0); + compile(m); + + m.invoke(null, start, stop, length, offset0); + assertIsCompiled(m); + try { + m.invoke(null, start, stop, length, offset1); + throw new RuntimeException("should have thrown"); + } catch(InvocationTargetException e) { + if (!(e.getCause() instanceof IndexOutOfBoundsException)) { + throw new RuntimeException("unexpected exception"); + } + } + assertIsNotCompiled(m); + } + + private static void testConditional(String method, long start, long stop, long length, long offset0, long offset1, long start1, long stop1) throws Exception { + Method m; + + if (start1 != start) { + m = newClassLoader().loadClass("TestLongRangeCheck").getDeclaredMethod(method, long.class, long.class, long.class, long.class, long.class, long.class); + m.invoke(null, start, stop, length, offset0, start, stop); + compile(m); + + m.invoke(null, start, stop, length, offset0, start, stop); + assertIsCompiled(m); + try { + m.invoke(null, start, stop, length, offset1, start1-1, stop1); + throw new RuntimeException("should have thrown"); + } catch(InvocationTargetException e) { + if (!(e.getCause() instanceof IndexOutOfBoundsException)) { + throw new RuntimeException("unexpected exception"); + } + } + assertIsNotCompiled(m); + } + + if (stop1 != stop) { + m = newClassLoader().loadClass("TestLongRangeCheck").getDeclaredMethod(method, long.class, long.class, long.class, long.class, long.class, long.class); + m.invoke(null, start, stop, length, offset0, start, stop); + compile(m); + + m.invoke(null, start, stop, length, offset0, start, stop); + assertIsCompiled(m); + try { + m.invoke(null, start, stop, length, offset1, start1, stop1+1); + throw new RuntimeException("should have thrown"); + } catch(InvocationTargetException e) { + if (!(e.getCause() instanceof IndexOutOfBoundsException)) { + throw new RuntimeException("unexpected exception"); + } + } + assertIsNotCompiled(m); + } + + m = newClassLoader().loadClass("TestLongRangeCheck").getDeclaredMethod(method, long.class, long.class, long.class, long.class, long.class, long.class); + m.invoke(null, start, stop, length, offset0, start, stop); + compile(m); + + m.invoke(null, start, stop, length, offset0, start, stop); + assertIsCompiled(m); + + m.invoke(null, start, stop, length, offset1, start1, stop1); + assertIsCompiled(m); + } public static void main(String[] args) throws Exception { @@ -157,42 +224,20 @@ public class TestLongRangeCheck { test("testStridePosNotOneScaleNeg", -v, v, v * 2, v-1); // offset causes overflow - - { - Method m = newClassLoader().loadClass("TestLongRangeCheck").getDeclaredMethod("testStridePosScalePos", long.class, long.class, long.class, long.class); - m.invoke(null, 0, 100, 100, 0); - compile(m); - - m.invoke(null, 0, 100, 100, 0); - assertIsCompiled(m); - try { - m.invoke(null, 0, 100, 100, Long.MAX_VALUE - 50); - throw new RuntimeException("should have thrown"); - } catch(InvocationTargetException e) { - if (!(e.getCause() instanceof IndexOutOfBoundsException)) { - throw new RuntimeException("unexpected exception"); - } - } - assertIsNotCompiled(m); - } + testOverflow("testStridePosScalePos", 0, 100, 100, 0, Long.MAX_VALUE - 50); + testOverflow("testStrideNegScaleNeg", 0, 100, 100, 100, Long.MIN_VALUE + 50); + testOverflow("testStrideNegScalePos", 0, 100, 100, 0, Long.MAX_VALUE - 50); + testOverflow("testStridePosScaleNeg", 0, 100, 100, 99, Long.MIN_VALUE + 50); // no spurious deopt if the range check doesn't fail because not executed - { - Method m = newClassLoader().loadClass("TestLongRangeCheck").getDeclaredMethod("testStridePosScalePosConditional", long.class, long.class, long.class, long.class, long.class, long.class); - m.invoke(null, 0, 100, 100, 0, 0, 100); - compile(m); - - m.invoke(null, 0, 100, 100, -50, 50, 100); - assertIsCompiled(m); - } - { - Method m = newClassLoader().loadClass("TestLongRangeCheck").getDeclaredMethod("testStridePosScalePosConditional", long.class, long.class, long.class, long.class, long.class, long.class); - m.invoke(null, 0, 100, 100, 0, 0, 100); - compile(m); - - m.invoke(null, 0, 100, Long.MAX_VALUE, Long.MAX_VALUE - 50, 0, 50); - assertIsCompiled(m); - } + testConditional("testStridePosScalePosConditional", 0, 100, 100, 0, -50, 50, 100); + testConditional("testStridePosScalePosConditional", 0, 100, Long.MAX_VALUE, 0, Long.MAX_VALUE - 50, 0, 50); + testConditional("testStrideNegScaleNegConditional", 0, 100, 100, 100, 50, 0, 51); + testConditional("testStrideNegScaleNegConditional", 0, 100, Long.MAX_VALUE, 100, Long.MIN_VALUE + 50, 52, 100); + testConditional("testStrideNegScalePosConditional", 0, 100, 100, 0, -50, 50, 100); + testConditional("testStrideNegScalePosConditional", 0, 100, Long.MAX_VALUE, 100, Long.MAX_VALUE - 50, 0, 50); + testConditional("testStridePosScaleNegConditional", 0, 100, 100, 99, 50, 0, 51); + testConditional("testStridePosScaleNegConditional", 0, 100, Long.MAX_VALUE, 99, Long.MIN_VALUE + 50, 52, 100); test("testStridePosScalePosInIntLoop", 0, 100, 100, 0); @@ -221,40 +266,19 @@ public class TestLongRangeCheck { test("testStridePosNotOneScaleNegInIntLoop", -v, v, v * 4, 2 * v - 1); // offset causes overflow - { - Method m = newClassLoader().loadClass("TestLongRangeCheck").getDeclaredMethod("testStridePosScalePosInIntLoop", long.class, long.class, long.class, long.class); - m.invoke(null, 0, 100, 100, 0); - compile(m); - - m.invoke(null, 0, 100, 100, 0); - assertIsCompiled(m); - try { - m.invoke(null, 0, 100, 100, Long.MAX_VALUE - 50); - throw new RuntimeException("should have thrown"); - } catch(InvocationTargetException e) { - if (!(e.getCause() instanceof IndexOutOfBoundsException)) { - throw new RuntimeException("unexpected exception"); - } - } - assertIsNotCompiled(m); - } + testOverflow("testStridePosScalePosInIntLoop", 0, 100, 100, 0, Long.MAX_VALUE - 50); + testOverflow("testStrideNegScaleNegInIntLoop", 0, 100, 100, 100, Long.MIN_VALUE + 50); + testOverflow("testStrideNegScalePosInIntLoop", 0, 100, 100, 0, Long.MAX_VALUE - 50); + testOverflow("testStridePosScaleNegInIntLoop", 0, 100, 100, 99, Long.MIN_VALUE + 50); // no spurious deopt if the range check doesn't fail because not executed - { - Method m = newClassLoader().loadClass("TestLongRangeCheck").getDeclaredMethod("testStridePosScalePosConditional", long.class, long.class, long.class, long.class, long.class, long.class); - m.invoke(null, 0, 100, 100, 0, 0, 100); - compile(m); - - m.invoke(null, 0, 100, 100, -50, 50, 100); - assertIsCompiled(m); - } - { - Method m = newClassLoader().loadClass("TestLongRangeCheck").getDeclaredMethod("testStridePosScalePosConditional", long.class, long.class, long.class, long.class, long.class, long.class); - m.invoke(null, 0, 100, 100, 0, 0, 100); - compile(m); - - m.invoke(null, 0, 100, Long.MAX_VALUE, Long.MAX_VALUE - 50, 0, 50); - assertIsCompiled(m); - } + testConditional("testStridePosScalePosConditionalInIntLoop", 0, 100, 100, 0, -50, 50, 100); + testConditional("testStridePosScalePosConditionalInIntLoop", 0, 100, Long.MAX_VALUE, 0, Long.MAX_VALUE - 50, 0, 50); + testConditional("testStrideNegScaleNegConditionalInIntLoop", 0, 100, 100, 100, 50, 0, 51); + testConditional("testStrideNegScaleNegConditionalInIntLoop", 0, 100, Long.MAX_VALUE, 100, Long.MIN_VALUE + 50, 52, 100); + testConditional("testStrideNegScalePosConditionalInIntLoop", 0, 100, 100, 0, -50, 50, 100); + testConditional("testStrideNegScalePosConditionalInIntLoop", 0, 100, Long.MAX_VALUE, 100, Long.MAX_VALUE - 50, 0, 50); + testConditional("testStridePosScaleNegConditionalInIntLoop", 0, 100, 100, 99, 50, 0, 51); + testConditional("testStridePosScaleNegConditionalInIntLoop", 0, 100, Long.MAX_VALUE, 99, Long.MIN_VALUE + 50, 52, 100); test("testStridePosScalePosNotOneInIntLoop2", 0, 100, 1090, 0); @@ -411,6 +435,36 @@ public class TestLongRangeCheck { } } + public static void testStrideNegScaleNegConditional(long start, long stop, long length, long offset, long start2, long stop2) { + final long scale = -1; + final long stride = 1; + for (long i = stop; i > start; i -= stride) { + if (i >= start2 && i < stop2) { + Preconditions.checkIndex(scale * i + offset, length, null); + } + } + } + + public static void testStrideNegScalePosConditional(long start, long stop, long length, long offset, long start2, long stop2) { + final long scale = 1; + final long stride = 1; + for (long i = stop-1; i >= start; i -= stride) { + if (i >= start2 && i < stop2) { + Preconditions.checkIndex(scale * i + offset, length, null); + } + } + } + + public static void testStridePosScaleNegConditional(long start, long stop, long length, long offset, long start2, long stop2) { + final long scale = -1; + final long stride = 1; + for (long i = start; i < stop; i += stride) { + if (i >= start2 && i < stop2) { + Preconditions.checkIndex(scale * i + offset, length, null); + } + } + } + private static void checkInputs(long... inputs) { for (int i = 0; i < inputs.length; i++) { if ((long)((int)inputs[i]) != inputs[i]) { @@ -529,7 +583,6 @@ public class TestLongRangeCheck { public static void testStridePosScalePosConditionalInIntLoop(long start, long stop, long length, long offset, long start2, long stop2) { checkInputs(start, stop, start2, stop2); - Preconditions.checkIndex(0, length, null); final long scale = 1; final int stride = 1; for (int i = (int)start; i < (int)stop; i += stride) { @@ -539,6 +592,39 @@ public class TestLongRangeCheck { } } + public static void testStrideNegScaleNegConditionalInIntLoop(long start, long stop, long length, long offset, long start2, long stop2) { + checkInputs(start, stop, start2, stop2); + final long scale = -1; + final int stride = 1; + for (int i = (int)stop; i > (int)start; i -= stride) { + if (i >= (int)start2 && i < (int)stop2) { + Preconditions.checkIndex(scale * i + offset, length, null); + } + } + } + + public static void testStrideNegScalePosConditionalInIntLoop(long start, long stop, long length, long offset, long start2, long stop2) { + checkInputs(start, stop, start2, stop2); + final long scale = 1; + final int stride = 1; + for (int i = (int)(stop-1); i >= (int)start; i -= stride) { + if (i >= (int)start2 && i < (int)stop2) { + Preconditions.checkIndex(scale * i + offset, length, null); + } + } + } + + public static void testStridePosScaleNegConditionalInIntLoop(long start, long stop, long length, long offset, long start2, long stop2) { + checkInputs(start, stop, start2, stop2); + final long scale = -1; + final int stride = 1; + for (int i = (int)start; i < (int)stop; i += stride) { + if (i >= (int)start2 && i < (int)stop2) { + Preconditions.checkIndex(scale * i + offset, length, null); + } + } + } + public static void testStridePosScalePosNotOneInIntLoop2(long start, long stop, long length, long offset) { checkInputs(start, stop); final int scale = 11; diff --git a/test/hotspot/jtreg/compiler/runtime/Test6826736.java b/test/hotspot/jtreg/compiler/runtime/Test6826736.java index 2f078506e55f3f5455873db3f68304302bc1ca9b..0b028947f7766b3628d438f4da9e68acfb64d5c7 100644 --- a/test/hotspot/jtreg/compiler/runtime/Test6826736.java +++ b/test/hotspot/jtreg/compiler/runtime/Test6826736.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 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 @@ -26,6 +26,7 @@ * @bug 6826736 * @summary CMS: core dump with -XX:+UseCompressedOops * + * @requires vm.bits == 64 * @run main/othervm/timeout=600 -XX:+IgnoreUnrecognizedVMOptions -Xbatch * -XX:+ScavengeALot -XX:+UseCompressedOops -XX:HeapBaseMinAddress=32g * -XX:CompileThreshold=100 -XX:-BlockLayoutRotateLoops diff --git a/test/hotspot/jtreg/compiler/unsafe/TestMisalignedUnsafeAccess.java b/test/hotspot/jtreg/compiler/unsafe/TestMisalignedUnsafeAccess.java index 10d766cf122df8fe5636930e2a76dd2c33e7b99c..84752a0ccf0069189bf4f63482432a7592c78c64 100644 --- a/test/hotspot/jtreg/compiler/unsafe/TestMisalignedUnsafeAccess.java +++ b/test/hotspot/jtreg/compiler/unsafe/TestMisalignedUnsafeAccess.java @@ -37,7 +37,7 @@ import jdk.test.lib.Asserts; public class TestMisalignedUnsafeAccess { - private static final Unsafe UNSAFE = Unsafe.getUnsafe();; + private static final Unsafe UNSAFE = Unsafe.getUnsafe(); private static short onHeapStaticMemory; // For static field testing private static final Object onHeapStaticMemoryBase; diff --git a/test/hotspot/jtreg/compiler/unsafe/UnsafeCopyMemory.java b/test/hotspot/jtreg/compiler/unsafe/UnsafeCopyMemory.java index 51cbb5e8c2fb79678b9c140f003232d87cbe1bf0..950fef40ec0f0a8881b65d49d6cfdf25d2ee00ac 100644 --- a/test/hotspot/jtreg/compiler/unsafe/UnsafeCopyMemory.java +++ b/test/hotspot/jtreg/compiler/unsafe/UnsafeCopyMemory.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 @@ -36,11 +36,14 @@ package compiler.unsafe; import jdk.internal.misc.Unsafe; +import java.nio.ByteOrder; import static jdk.test.lib.Asserts.assertEQ; public class UnsafeCopyMemory { static private Unsafe UNSAFE = Unsafe.getUnsafe(); + static final boolean IS_BIG_ENDIAN = ByteOrder.nativeOrder() == ByteOrder.BIG_ENDIAN; + // On-heap arrays static int[] srcArr = new int[1]; static int[] dstArr = new int[1]; @@ -104,8 +107,12 @@ public class UnsafeCopyMemory { srcArr [readIdx] = v1; dstArrL[writeIdx] = v2; + // On LE systems, low-order bytes of long and int overlap, but + // on BE systems, they differ by the size of an int. + long mismatchedOffset = Unsafe.ARRAY_LONG_BASE_OFFSET + (IS_BIG_ENDIAN ? 4 : 0); + UNSAFE.copyMemory(srcArr, Unsafe.ARRAY_INT_BASE_OFFSET, - dstArrL, Unsafe.ARRAY_LONG_BASE_OFFSET, 4); // mismatched + dstArrL, mismatchedOffset, 4); // mismatched long r = resArrL[0]; // snapshot srcArr[readIdx] = v3; @@ -156,6 +163,7 @@ public class UnsafeCopyMemory { Object srcArrLocal = (flag ? srcArrIntLocal : srcArrLongLocal); long srcOffset = (flag ? Unsafe.ARRAY_INT_BASE_OFFSET : Unsafe.ARRAY_LONG_BASE_OFFSET); + srcOffset += (!flag && IS_BIG_ENDIAN ? 4 : 0); srcArrIntLocal[0] = v1; srcArrLongLocal[0] = v1; @@ -179,6 +187,7 @@ public class UnsafeCopyMemory { Object dstArrLocal = (flag ? dstArrIntLocal : dstArrLongLocal); long dstOffset = (flag ? Unsafe.ARRAY_INT_BASE_OFFSET : Unsafe.ARRAY_LONG_BASE_OFFSET); + dstOffset += (!flag && IS_BIG_ENDIAN ? 4 : 0); srcArr[readIdx] = v1; dstArrIntLocal[0] = v2; diff --git a/test/hotspot/jtreg/compiler/vectorapi/TestMaskedMacroLogicVector.java b/test/hotspot/jtreg/compiler/vectorapi/TestMaskedMacroLogicVector.java index e5f2e34040d288e5abe6d4a544972ce6348da4ed..0c303f8c39f0ed7fd05ea53b3cfce1f47418ff04 100644 --- a/test/hotspot/jtreg/compiler/vectorapi/TestMaskedMacroLogicVector.java +++ b/test/hotspot/jtreg/compiler/vectorapi/TestMaskedMacroLogicVector.java @@ -37,9 +37,6 @@ package compiler.vectorapi; import java.util.concurrent.Callable; import compiler.lib.ir_framework.*; -import compiler.lib.ir_framework.driver.IRViolationException; -import jdk.test.lib.Asserts; -import jdk.test.lib.Asserts; import jdk.test.lib.Utils; import java.util.Random; diff --git a/test/hotspot/jtreg/compiler/vectorization/TestPopCountVectorLong.java b/test/hotspot/jtreg/compiler/vectorization/TestPopCountVectorLong.java index e80c7cfac954101dc0049b47d1b766ef6b598543..49e3a428c303919355e95738d989c8e29c7de399 100644 --- a/test/hotspot/jtreg/compiler/vectorization/TestPopCountVectorLong.java +++ b/test/hotspot/jtreg/compiler/vectorization/TestPopCountVectorLong.java @@ -24,9 +24,8 @@ /** * @test * @summary Test vectorization of popcount for Long -* @requires vm.cpu.features ~= ".*avx512dq.*" -* @requires vm.cpu.features ~= ".*vpopcntdq.*" * @requires vm.compiler2.enabled +* @requires vm.cpu.features ~= ".*avx512bw.*" * @requires os.arch=="x86" | os.arch=="i386" | os.arch=="amd64" | os.arch=="x86_64" * @library /test/lib / * @run driver compiler.vectorization.TestPopCountVectorLong diff --git a/test/hotspot/jtreg/containers/cgroup/PlainRead.java b/test/hotspot/jtreg/containers/cgroup/PlainRead.java index 3bd74d9437e26bc103579dc3f67b1f9b7cf98d09..d09383744090049da33810a43379235855b80e0e 100644 --- a/test/hotspot/jtreg/containers/cgroup/PlainRead.java +++ b/test/hotspot/jtreg/containers/cgroup/PlainRead.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 @@ -50,7 +50,7 @@ public class PlainRead { static final String good_value = "(\\d+|-1|-2|Unlimited)"; static final String bad_value = "(failed)"; - static final String[] variables = {"Memory Limit is:", "CPU Shares is:", "CPU Quota is:", "CPU Period is:", "active_processor_count:"}; + static final String[] variables = {"Memory Limit is:", "CPU Quota is:", "CPU Period is:", "active_processor_count:"}; static public void isContainer(OutputAnalyzer oa) { for (String v: variables) { diff --git a/test/hotspot/jtreg/containers/docker/TestCPUAwareness.java b/test/hotspot/jtreg/containers/docker/TestCPUAwareness.java index d8246bfc2c58ea36f5b69bbf453f542863a3f3c9..a72441182cd878923cbf2aa264ce1fc1c7dfd817 100644 --- a/test/hotspot/jtreg/containers/docker/TestCPUAwareness.java +++ b/test/hotspot/jtreg/containers/docker/TestCPUAwareness.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 @@ -100,6 +100,11 @@ public class TestCPUAwareness { String cpuSetStr = CPUSetsReader.readFromProcStatus("Cpus_allowed_list"); System.out.println("cpuSetStr = " + cpuSetStr); + // OLD = use the deprecated -XX:+UseContainerCpuShares flag, which + // will be removed in the next JDK release. See JDK-8281181. + boolean OLD = true; + boolean NEW = false; + if (cpuSetStr == null) { System.out.printf("The cpuset test cases are skipped"); } else { @@ -108,23 +113,32 @@ public class TestCPUAwareness { // Test subset of cpuset with one element if (cpuSet.size() >= 1) { String testCpuSet = CPUSetsReader.listToString(cpuSet, 1); - testAPCCombo(testCpuSet, 200*1000, 100*1000, 4*1024, true, 1); + testAPCCombo(OLD, testCpuSet, 200*1000, 100*1000, 4*1024, true, 1); + testAPCCombo(NEW, testCpuSet, 200*1000, 100*1000, 4*1024, true, 1); } // Test subset of cpuset with two elements if (cpuSet.size() >= 2) { String testCpuSet = CPUSetsReader.listToString(cpuSet, 2); - testAPCCombo(testCpuSet, 200*1000, 100*1000, 4*1024, true, 2); - testAPCCombo(testCpuSet, 200*1000, 100*1000, 1023, true, 2); - testAPCCombo(testCpuSet, 200*1000, 100*1000, 1023, false, 1); + testAPCCombo(OLD, testCpuSet, 200*1000, 100*1000, 4*1024, true, 2); + testAPCCombo(OLD, testCpuSet, 200*1000, 100*1000, 1023, true, 2); + testAPCCombo(OLD, testCpuSet, 200*1000, 100*1000, 1023, false,1); + + testAPCCombo(NEW, testCpuSet, 200*1000, 100*1000, 4*1024, true, 2); + testAPCCombo(NEW, testCpuSet, 200*1000, 100*1000, 1023, true, 2); + testAPCCombo(NEW, testCpuSet, 200*1000, 100*1000, 1023, false,2); } // Test subset of cpuset with three elements if (cpuSet.size() >= 3) { String testCpuSet = CPUSetsReader.listToString(cpuSet, 3); - testAPCCombo(testCpuSet, 100*1000, 100*1000, 2*1024, true, 1); - testAPCCombo(testCpuSet, 200*1000, 100*1000, 1023, true, 2); - testAPCCombo(testCpuSet, 200*1000, 100*1000, 1023, false, 1); + testAPCCombo(OLD, testCpuSet, 100*1000, 100*1000, 2*1024, true, 1); + testAPCCombo(OLD, testCpuSet, 200*1000, 100*1000, 1023, true, 2); + testAPCCombo(OLD, testCpuSet, 200*1000, 100*1000, 1023, false,1); + + testAPCCombo(NEW, testCpuSet, 100*1000, 100*1000, 2*1024, true, 1); + testAPCCombo(NEW, testCpuSet, 200*1000, 100*1000, 1023, true, 2); + testAPCCombo(NEW, testCpuSet, 200*1000, 100*1000, 1023, false,2); } } } @@ -181,8 +195,11 @@ public class TestCPUAwareness { } - // Test correctess of automatically selected active processor cound - private static void testAPCCombo(String cpuset, int quota, int period, int shares, + // Test correctess of automatically selected active processor count + // Note: when -XX:+UseContainerCpuShares is removed, + // useContainerCpuShares, shares, and usePreferContainerQuotaForCPUCount + // should also be removed. + private static void testAPCCombo(boolean useContainerCpuShares, String cpuset, int quota, int period, int shares, boolean usePreferContainerQuotaForCPUCount, int expectedAPC) throws Exception { Common.logNewTestCase("test APC Combo"); @@ -190,6 +207,7 @@ public class TestCPUAwareness { System.out.println("quota = " + quota); System.out.println("period = " + period); System.out.println("shares = " + shares); + System.out.println("useContainerCpuShares = " + useContainerCpuShares); System.out.println("usePreferContainerQuotaForCPUCount = " + usePreferContainerQuotaForCPUCount); System.out.println("expectedAPC = " + expectedAPC); @@ -201,13 +219,15 @@ public class TestCPUAwareness { .addDockerOpts("--cpu-quota=" + quota) .addDockerOpts("--cpu-shares=" + shares); - if (!usePreferContainerQuotaForCPUCount) opts.addJavaOpts("-XX:-PreferContainerQuotaForCPUCount"); + if (useContainerCpuShares) opts.addJavaOpts("-XX:+UseContainerCpuShares"); // deprecated + if (!usePreferContainerQuotaForCPUCount) opts.addJavaOpts("-XX:-PreferContainerQuotaForCPUCount"); // deprecated Common.run(opts) .shouldMatch("active_processor_count.*" + expectedAPC); } + // Note: when -XX:+UseContainerCpuShares is removed, this test should also be removed. private static void testCpuShares(int shares, int expectedAPC) throws Exception { Common.logNewTestCase("test cpu shares, shares = " + shares); System.out.println("expectedAPC = " + expectedAPC); @@ -216,6 +236,7 @@ public class TestCPUAwareness { DockerRunOptions opts = Common.newOpts(imageName) .addDockerOpts("--cpu-shares=" + shares); + opts.addJavaOpts("-XX:+UseContainerCpuShares"); // deprecated OutputAnalyzer out = Common.run(opts); // Cgroups v2 needs to do some scaling of raw shares values. Hence, // 256 CPU shares come back as 264. Raw value written to cpu.weight diff --git a/test/hotspot/jtreg/gc/arguments/TestParallelGCThreads.java b/test/hotspot/jtreg/gc/arguments/TestParallelGCThreads.java index 61f8c99d25b0806a5c3f3700b6f1a2067c8d714c..26ee75d467c44095038b3c1c69ad1244f035e94c 100644 --- a/test/hotspot/jtreg/gc/arguments/TestParallelGCThreads.java +++ b/test/hotspot/jtreg/gc/arguments/TestParallelGCThreads.java @@ -115,15 +115,12 @@ public class TestParallelGCThreads { // 4294967295 == (unsigned int) -1 // So setting ParallelGCThreads=4294967295 should give back 4294967295 - // and setting ParallelGCThreads=4294967296 should give back 0. (SerialGC is ok with ParallelGCThreads=0) - for (long i = 4294967295L; i <= 4294967296L; i++) { - long count = getParallelGCThreadCount( - "-XX:+UseSerialGC", - "-XX:ParallelGCThreads=" + i, - "-XX:+PrintFlagsFinal", - "-version"); - Asserts.assertEQ(count, i % 4294967296L, "Specifying ParallelGCThreads=" + i + " does not set the thread count properly!"); - } + long count = getParallelGCThreadCount( + "-XX:+UseSerialGC", + "-XX:ParallelGCThreads=4294967295", + "-XX:+PrintFlagsFinal", + "-version"); + Asserts.assertEQ(count, 4294967295L, "Specifying ParallelGCThreads=4294967295 does not set the thread count properly!"); } public static long getParallelGCThreadCount(String... flags) throws Exception { diff --git a/test/hotspot/jtreg/gc/shenandoah/compiler/TestBarrierAboveProj.java b/test/hotspot/jtreg/gc/shenandoah/compiler/TestBarrierAboveProj.java new file mode 100644 index 0000000000000000000000000000000000000000..560b6f34617056ea38a8f16bf5ad468a52e71b73 --- /dev/null +++ b/test/hotspot/jtreg/gc/shenandoah/compiler/TestBarrierAboveProj.java @@ -0,0 +1,71 @@ +/* + * 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. + */ + +/* + * @test + * bug 8281811 + * @summary assert(_base == Tuple) failed: Not a Tuple after JDK-8280799 + * @requires vm.gc.Shenandoah + * @run main/othervm -XX:+UseShenandoahGC -XX:-BackgroundCompilation -XX:LoopMaxUnroll=1 TestBarrierAboveProj + */ + + +public class TestBarrierAboveProj { + private static C objField = new C(); + private static final Object[] arrayField = new Object[1000]; + private static volatile int volatileField; + + public static void main(String[] args) { + for (int i = 0; i < 20_000; i++) { + test1(); + test2(); + } + } + + private static float test1() { + float v = 1; + for (int i = 1; i < 1000; i++) { + if (objField == arrayField[i]) { + return v; + } + v *= 2; + } + return v; + } + + private static float test2() { + float v = 1; + volatileField = 0x42; + for (int i = 1; i < 1000; i++) { + if (objField == arrayField[i]) { + return v; + } + v *= 2; + } + return v; + } + + private static class C { + public float floatField; + } +} diff --git a/test/hotspot/jtreg/runtime/8176717/TestInheritFD.java b/test/hotspot/jtreg/runtime/8176717/TestInheritFD.java index 37c5280d2367fcf251daab9404e03deb3787293a..c84bc7e0159918365d9daeed4533410565220e00 100644 --- a/test/hotspot/jtreg/runtime/8176717/TestInheritFD.java +++ b/test/hotspot/jtreg/runtime/8176717/TestInheritFD.java @@ -21,6 +21,7 @@ * questions. */ +import static java.lang.Character.isDigit; import static java.lang.Long.parseLong; import static java.lang.System.getProperty; import static java.nio.file.Files.readAllBytes; @@ -40,6 +41,7 @@ import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStreamReader; import java.util.Collection; +import java.util.concurrent.TimeUnit; import java.util.Optional; import java.util.stream.Stream; @@ -60,17 +62,18 @@ import java.util.stream.Stream; * * This test is performed in three steps. The first VM starts a second VM with * gc logging enabled. The second VM starts a third VM and redirects the third - * VMs output to the first VM, it then exits and hopefully closes its log file. + * VMs output to the first VM. The second VM then exits and hopefully closes + * its log file. * - * The third VM waits for the second to exit and close its log file. After that, - * the third VM tries to rename the log file of the second VM. If it succeeds in - * doing so it means that the third VM did not inherit the open log file - * (windows can not rename opened files easily) + * The third VM waits for the second to exit and close its log file. + * On Windows, the third VM tries to rename the log file of the second VM. + * If it succeeds in doing so it means that the third VM did not inherit + * the open log file (windows cannot rename opened files easily). + * On unix like systems, the third VM uses "lsof" for verification. * - * The third VM communicates the success to rename the file by printing "CLOSED - * FD". The first VM checks that the string was printed by the third VM. - * - * On unix like systems "lsof" is used. + * The third VM communicates success by printing "RETAINS FD". The first VM + * waits for the third VM to exit and checks that the string was printed by + * the third VM. */ public class TestInheritFD { @@ -80,9 +83,145 @@ public class TestInheritFD { public static final String EXIT = "VM RESULT => VM EXIT"; public static final String LOG_SUFFIX = ".strangelogsuffixthatcanbecheckedfor"; public static final String USER_DIR = System.getProperty("user.dir"); + public static final String LSOF_PID_PREFIX = " VM lsof pid="; + public static final String SECOND_VM_PID_PREFIX = "Second VM pid="; + public static final String THIRD_VM_PID_PREFIX = "Third VM pid="; + public static final String THIRD_VM_WAITING_PREFIX = "Third VM waiting for second VM pid="; + + public static float timeoutFactor = Float.parseFloat(System.getProperty("test.timeout.factor", "1.0")); + public static long subProcessTimeout = (long)(15L * timeoutFactor); + + // Extract a pid from the specified String at the specified start offset. + private static long extractPidFromStringOffset(String str, int start) { + int end; + for (end = start; end < str.length(); end++) { + if (!isDigit(str.charAt(end))) { + break; + } + } + if (start == end) { // no digits at all + return -1; + } + return parseLong(str.substring(start, end)); + } + + // Wait for the sub-process pids identified in commFile to finish executing. + // Returns true if RETAINS_FD was found in the commFile and false otherwise. + private static boolean waitForSubPids(File commFile) throws Exception { + String out = ""; + int sleepCnt = 0; + long secondVMPID = -1; + long secondVMlsofPID = -1; + long thirdVMPID = -1; + long thirdVMlsofPID = -1; + // Only have to gather info until the doneWithPattern shows up in the output: + String doneWithPattern; + if (isWindows()) { + doneWithPattern = THIRD_VM_PID_PREFIX; + } else { + doneWithPattern = "Third" + LSOF_PID_PREFIX; + } + do { + out = new String(readAllBytes(commFile.toPath())); + if (secondVMPID == -1) { + int ind = out.indexOf(SECOND_VM_PID_PREFIX); + if (ind != -1) { + int startPid = ind + SECOND_VM_PID_PREFIX.length(); + secondVMPID = extractPidFromStringOffset(out, startPid); + System.out.println("secondVMPID=" + secondVMPID); + } + } + if (!isWindows() && secondVMlsofPID == -1) { + String prefix = "Second" + LSOF_PID_PREFIX; + int ind = out.indexOf(prefix); + if (ind != -1) { + int startPid = ind + prefix.length(); + secondVMlsofPID = extractPidFromStringOffset(out, startPid); + System.out.println("secondVMlsofPID=" + secondVMlsofPID); + } + } + if (thirdVMPID == -1) { + int ind = out.indexOf(THIRD_VM_PID_PREFIX); + if (ind != -1) { + int startPid = ind + THIRD_VM_PID_PREFIX.length(); + thirdVMPID = extractPidFromStringOffset(out, startPid); + System.out.println("thirdVMPID=" + thirdVMPID); + } + } + if (!isWindows() && thirdVMlsofPID == -1) { + String prefix = "Third" + LSOF_PID_PREFIX; + int ind = out.indexOf(prefix); + if (ind != -1) { + int startPid = ind + prefix.length(); + thirdVMlsofPID = extractPidFromStringOffset(out, startPid); + System.out.println("thirdVMlsofPID=" + thirdVMlsofPID); + } + } + Thread.sleep(100); + sleepCnt++; + } while (!out.contains(doneWithPattern) && !out.contains(EXIT)); + + System.out.println("Called Thread.sleep(100) " + sleepCnt + " times."); + + long subPids[] = new long[4]; // At most 4 pids to check. + String subNames[] = new String[4]; // At most 4 names for those pids. + int ind = 0; + if (!isWindows() && secondVMlsofPID != -1) { + // The second VM's lsof cmd should be the first non-windows sub-process to finish: + subPids[ind] = secondVMlsofPID; + subNames[ind] = "second VM lsof"; + ind++; + } + // The second VM should the second non-windows or first windows sub-process to finish: + subPids[ind] = secondVMPID; + subNames[ind] = "second VM"; + ind++; + if (!isWindows() && thirdVMlsofPID != -1) { + // The third VM's lsof cmd should be the third non-windows sub-process to finish: + subPids[ind] = thirdVMlsofPID; + subNames[ind] = "third VM lsof"; + ind++; + } + // The third VM should the last sub-process to finish: + subPids[ind] = thirdVMPID; + subNames[ind] = "third VM"; + ind++; + if (isWindows()) { + // No lsof pids on windows so we use fewer array slots. + // Make sure they are marked as not used. + for (; ind < subPids.length; ind++) { + subPids[ind] = -1; + } + } + + try { + for (ind = 0; ind < subPids.length; ind++) { + if (subPids[ind] == -1) { + continue; + } + System.out.print("subs[" + ind + "]={pid=" + subPids[ind] + ", name=" + subNames[ind] + "}"); + ProcessHandle.of(subPids[ind]).ifPresent(handle -> handle.onExit().orTimeout(subProcessTimeout, TimeUnit.SECONDS).join()); + System.out.println(" finished."); + } + } catch (Exception e) { + // Terminate the "subs" line from above: + System.out.println(" Exception was thrown while trying to join() subPids: " + e.toString()); + throw e; + } finally { + // Reread to get everything in the commFile: + out = new String(readAllBytes(commFile.toPath())); + System.out.println(""); + System.out.println(out); + System.out.println(""); + } + + return out.contains(RETAINS_FD); + } // first VM public static void main(String[] args) throws Exception { + System.out.println("subProcessTimeout=" + subProcessTimeout + " seconds."); + System.out.println("First VM starts."); String logPath = Utils.createTempFile("logging", LOG_SUFFIX).toFile().getName(); File commFile = Utils.createTempFile("communication", ".txt").toFile(); @@ -99,24 +238,18 @@ public class TestInheritFD { pb.redirectOutput(commFile); // use temp file to communicate between processes pb.start(); - String out = ""; - do { - out = new String(readAllBytes(commFile.toPath())); - Thread.sleep(100); - System.out.println("SLEEP 100 millis"); - } while (!out.contains(EXIT)); - - System.out.println(out); - if (out.contains(RETAINS_FD)) { - System.out.println("Log file was not inherited by third VM"); + if (waitForSubPids(commFile)) { + System.out.println("Log file was not inherited by third VM."); } else { - throw new RuntimeException("could not match: " + RETAINS_FD); + throw new RuntimeException("Log file was leaked to the third VM."); } + System.out.println("First VM ends."); } static class VMStartedWithLogging { // second VM public static void main(String[] args) throws IOException, InterruptedException { + System.out.println(SECOND_VM_PID_PREFIX + ProcessHandle.current().pid()); ProcessBuilder pb = createJavaProcessBuilder( "-Dtest.jdk=" + getProperty("test.jdk"), VMShouldNotInheritFileDescriptors.class.getName(), @@ -126,30 +259,43 @@ public class TestInheritFD { pb.start(); if (!isWindows()) { - System.out.println("(Second VM) Open file descriptors:\n" + outputContainingFilenames().stream().collect(joining("\n"))); + System.out.println("(Second VM) Open file descriptors:\n" + outputContainingFilenames("Second").stream().collect(joining("\n"))); + } + if (false) { // Enable to simulate a timeout in the second VM. + Thread.sleep(300 * 1000); } + System.out.println("Second VM ends."); } } static class VMShouldNotInheritFileDescriptors { // third VM public static void main(String[] args) throws InterruptedException { + System.out.println(THIRD_VM_PID_PREFIX + ProcessHandle.current().pid()); try { File logFile = new File(args[0]); long parentPid = parseLong(args[1]); fakeLeakyJVM(false); // for debugging of test case + System.out.println(THIRD_VM_WAITING_PREFIX + parentPid); + ProcessHandle.of(parentPid).ifPresent(handle -> handle.onExit().orTimeout(subProcessTimeout, TimeUnit.SECONDS).join()); + if (isWindows()) { - windows(logFile, parentPid); + windows(logFile); } else { - Collection output = outputContainingFilenames(); + Collection output = outputContainingFilenames("Third"); System.out.println("(Third VM) Open file descriptors:\n" + output.stream().collect(joining("\n"))); System.out.println(findOpenLogFile(output) ? LEAKS_FD : RETAINS_FD); } + if (false) { // Enable to simulate a timeout in the third VM. + Thread.sleep(300 * 1000); + } } catch (Exception e) { - System.out.println(e.toString()); + System.out.println("Exception was thrown: " + e.toString()); + throw e; } finally { System.out.println(EXIT); + System.out.println("Third VM ends."); } } } @@ -165,9 +311,11 @@ public class TestInheritFD { } } - static Stream run(String... args){ + static Stream runLsof(String whichVM, String... args){ try { - return new BufferedReader(new InputStreamReader(new ProcessBuilder(args).start().getInputStream())).lines(); + Process lsof = new ProcessBuilder(args).start(); + System.out.println(whichVM + LSOF_PID_PREFIX + lsof.pid()); + return new BufferedReader(new InputStreamReader(lsof.getInputStream())).lines(); } catch (IOException e) { throw new RuntimeException(e); } @@ -186,12 +334,12 @@ public class TestInheritFD { return lsofCommandCache; } - static Collection outputContainingFilenames() { + static Collection outputContainingFilenames(String whichVM) { long pid = ProcessHandle.current().pid(); String[] command = lsofCommand().orElseThrow(() -> new RuntimeException("lsof like command not found")); // Only search the directory in which the VM is running (user.dir property). System.out.println("using command: " + command[0] + " -a +d " + USER_DIR + " " + command[1] + " " + pid); - return run(command[0], "-a", "+d", USER_DIR, command[1], "" + pid).collect(toList()); + return runLsof(whichVM, command[0], "-a", "+d", USER_DIR, command[1], "" + pid).collect(toList()); } static boolean findOpenLogFile(Collection fileNames) { @@ -208,9 +356,7 @@ public class TestInheritFD { .isPresent(); } - static void windows(File f, long parentPid) throws InterruptedException { - System.out.println("waiting for pid: " + parentPid); - ProcessHandle.of(parentPid).ifPresent(handle -> handle.onExit().join()); + static void windows(File f) throws InterruptedException { System.out.println("trying to rename file to the same name: " + f); System.out.println(f.renameTo(f) ? RETAINS_FD : LEAKS_FD); // this parts communicates a closed file descriptor by printing "VM RESULT => RETAINS FD" } diff --git a/test/hotspot/jtreg/runtime/CommandLine/PrintClasses.java b/test/hotspot/jtreg/runtime/CommandLine/PrintClasses.java new file mode 100644 index 0000000000000000000000000000000000000000..7c45e2ea02f74583459fe3b125a49a8984b53ae6 --- /dev/null +++ b/test/hotspot/jtreg/runtime/CommandLine/PrintClasses.java @@ -0,0 +1,51 @@ +/* + * 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. + */ + + +/* + * @test + * @bug 8275775 + * @summary Test jcmd VM.classes + * @library /test/lib + * @run main/othervm PrintClasses + */ + +import jdk.test.lib.process.OutputAnalyzer; +import jdk.test.lib.JDKToolFinder; + +public class PrintClasses { + public static void main(String args[]) throws Exception { + var pid = Long.toString(ProcessHandle.current().pid()); + var pb = new ProcessBuilder(); + + pb.command(new String[] { JDKToolFinder.getJDKTool("jcmd"), pid, "VM.classes"}); + var output = new OutputAnalyzer(pb.start()); + output.shouldNotContain("instance size"); + output.shouldContain(PrintClasses.class.getSimpleName()); + + pb.command(new String[] { JDKToolFinder.getJDKTool("jcmd"), pid, "VM.classes", "-verbose"}); + output = new OutputAnalyzer(pb.start()); + output.shouldContain("instance size"); + output.shouldContain(PrintClasses.class.getSimpleName()); + } +} diff --git a/test/hotspot/jtreg/runtime/CommandLine/VMDeprecatedOptions.java b/test/hotspot/jtreg/runtime/CommandLine/VMDeprecatedOptions.java index a8b5bb311941f67eea523686ff133d7b891d1c35..ee93c740cf136f7d1670ea7b561db05752c4335b 100644 --- a/test/hotspot/jtreg/runtime/CommandLine/VMDeprecatedOptions.java +++ b/test/hotspot/jtreg/runtime/CommandLine/VMDeprecatedOptions.java @@ -45,6 +45,8 @@ public class VMDeprecatedOptions { */ public static final String[][] DEPRECATED_OPTIONS; static { + // Use an ArrayList so platform-specific flags can be + // optionally added. ArrayList deprecated = new ArrayList( Arrays.asList(new String[][] { // deprecated non-alias flags: @@ -60,6 +62,10 @@ public class VMDeprecatedOptions { {"CreateMinidumpOnCrash", "false"} } )); + if (Platform.isLinux()) { + deprecated.add(new String[] {"UseContainerCpuShares", "false"}); + deprecated.add(new String[] {"PreferContainerQuotaForCPUCount", "true"}); + } DEPRECATED_OPTIONS = deprecated.toArray(new String[][]{}); }; diff --git a/test/hotspot/jtreg/runtime/CompressedOops/CompressedClassPointers.java b/test/hotspot/jtreg/runtime/CompressedOops/CompressedClassPointers.java index c46b32b220d9c76064b7ef8c6c8df64eb3e56d32..8e2033e73296273889d3c0797ff2c28b1cb24968 100644 --- a/test/hotspot/jtreg/runtime/CompressedOops/CompressedClassPointers.java +++ b/test/hotspot/jtreg/runtime/CompressedOops/CompressedClassPointers.java @@ -224,8 +224,8 @@ public class CompressedClassPointers { "-XX:+VerifyBeforeGC", "-version"); OutputAnalyzer output = new OutputAnalyzer(pb.start()); output.shouldContain("Narrow klass base: 0x0000000000000000"); - if (!Platform.isAArch64()) { - // Currently relax this test for Aarch64. + if (!Platform.isAArch64() && !Platform.isPPC()) { + // Currently relax this test for Aarch64 and ppc. output.shouldContain("Narrow klass shift: 0"); } output.shouldHaveExitValue(0); @@ -244,8 +244,8 @@ public class CompressedClassPointers { "-XX:+VerifyBeforeGC", "-version"); OutputAnalyzer output = new OutputAnalyzer(pb.start()); output.shouldContain("Narrow klass base: 0x0000000000000000"); - if (!Platform.isAArch64()) { - // Currently relax this test for Aarch64. + if (!Platform.isAArch64() && !Platform.isPPC()) { + // Currently relax this test for Aarch64 and ppc. output.shouldContain("Narrow klass shift: 0"); } output.shouldHaveExitValue(0); diff --git a/test/hotspot/jtreg/runtime/Thread/StopAtExit.java b/test/hotspot/jtreg/runtime/Thread/StopAtExit.java index 2255009320210785d342686c566cbbb956a6d41d..b997890e3476a1ba02844c5c52b575e654562cdd 100644 --- a/test/hotspot/jtreg/runtime/Thread/StopAtExit.java +++ b/test/hotspot/jtreg/runtime/Thread/StopAtExit.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 @@ -23,11 +23,13 @@ /** * @test - * @bug 8167108 8266130 + * @bug 8167108 8266130 8282704 * @summary Stress test java.lang.Thread.stop() at thread exit. + * @modules java.base/java.lang:open * @run main/othervm StopAtExit */ +import java.lang.reflect.Method; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; @@ -38,6 +40,10 @@ public class StopAtExit extends Thread { public CountDownLatch exitSyncObj = new CountDownLatch(1); public CountDownLatch startSyncObj = new CountDownLatch(1); + public StopAtExit(ThreadGroup group, Runnable target) { + super(group, target); + } + @Override public void run() { try { @@ -72,11 +78,18 @@ public class StopAtExit extends Thread { System.out.println("About to execute for " + timeMax + " seconds."); long count = 0; + long manualDestroyCnt = 0; + long manualTerminateCnt = 0; long start_time = System.currentTimeMillis(); while (System.currentTimeMillis() < start_time + (timeMax * 1000)) { count++; - StopAtExit thread = new StopAtExit(); + // Use my own ThreadGroup so the thread count is known and make + // it a daemon ThreadGroup so it is automatically destroyed when + // the thread is terminated. + ThreadGroup myTG = new ThreadGroup("myTG-" + count); + myTG.setDaemon(true); + StopAtExit thread = new StopAtExit(myTG, null); thread.start(); try { // Wait for the worker thread to get going. @@ -107,9 +120,52 @@ public class StopAtExit extends Thread { } catch (InterruptedException e) { throw new Error("Unexpected: " + e); } + // This stop() call happens after the join() so it should do + // nothing, but let's make sure. thread.stop(); + + if (myTG.activeCount() != 0) { + // If the ThreadGroup still has a count, then the thread + // received the async exception while in exit() so we need + // to do a manual terminate. + manualTerminateCnt++; + try { + threadTerminated(myTG, thread); + } catch (Exception e) { + throw new Error("threadTerminated() threw unexpected: " + e); + } + int activeCount = myTG.activeCount(); + if (activeCount != 0) { + throw new Error("threadTerminated() did not clean up " + + "worker thread: count=" + activeCount); + } + if (!myTG.isDestroyed()) { + throw new Error("threadTerminated() did not destroy " + + myTG.getName()); + } + } else if (!myTG.isDestroyed()) { + // If the ThreadGroup does not have a count, but is not + // yet destroyed, then the thread received the async + // exception while the thread was in the later stages of + // its threadTerminated() call so we need to do a manual + // destroy. + manualDestroyCnt++; + try { + myTG.destroy(); + } catch (Exception e) { + throw new Error("myTG.destroy() threw unexpected: " + e); + } + } } + if (manualDestroyCnt != 0) { + System.out.println("Manually destroyed ThreadGroup " + + manualDestroyCnt + " times."); + } + if (manualTerminateCnt != 0) { + System.out.println("Manually terminated Thread " + + manualTerminateCnt + " times."); + } System.out.println("Executed " + count + " loops in " + timeMax + " seconds."); @@ -120,6 +176,13 @@ public class StopAtExit extends Thread { } } + static void threadTerminated(ThreadGroup group, Thread thread) throws Exception { + // ThreadGroup.threadTerminated() is package private: + Method method = ThreadGroup.class.getDeclaredMethod("threadTerminated", Thread.class); + method.setAccessible(true); + method.invoke(group, thread); + } + public static void usage() { System.err.println("Usage: " + PROG_NAME + " [time_max]"); System.err.println("where:"); diff --git a/test/hotspot/jtreg/runtime/cds/DeterministicDump.java b/test/hotspot/jtreg/runtime/cds/DeterministicDump.java index 9cdba1fa922073290ee6c9da8e3e60ef44f71439..6e8ccffce278cf53267693eeb3527f3666708d3e 100644 --- a/test/hotspot/jtreg/runtime/cds/DeterministicDump.java +++ b/test/hotspot/jtreg/runtime/cds/DeterministicDump.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 @@ -54,6 +54,11 @@ public class DeterministicDump { baseArgs.add("-Xmx128M"); if (Platform.is64bit()) { + if (!compressed) { + System.out.println("CDS archives with uncompressed oops are still non-deterministic"); + System.out.println("See https://bugs.openjdk.java.net/browse/JDK-8282828"); + return; + } // These options are available only on 64-bit. String sign = (compressed) ? "+" : "-"; baseArgs.add("-XX:" + sign + "UseCompressedOops"); @@ -78,9 +83,12 @@ public class DeterministicDump { static String dump(ArrayList args, String... more) throws Exception { String logName = "SharedArchiveFile" + (id++); String archiveName = logName + ".jsa"; + String mapName = logName + ".map"; CDSOptions opts = (new CDSOptions()) .addPrefix("-Xlog:cds=debug") + .addPrefix("-Xlog:cds+map=trace:file=" + mapName + ":none:filesize=0") .setArchiveName(archiveName) + .addSuffix(args) .addSuffix(more); CDSTestUtils.createArchiveAndCheck(opts); diff --git a/test/hotspot/jtreg/runtime/cds/SharedBaseAddress.java b/test/hotspot/jtreg/runtime/cds/SharedBaseAddress.java index 761b5a05d294ec94c211e250f1b8991074afb62b..a7f31cf1a082f3f74e5db9175c76728338aac652 100644 --- a/test/hotspot/jtreg/runtime/cds/SharedBaseAddress.java +++ b/test/hotspot/jtreg/runtime/cds/SharedBaseAddress.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2021, 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 @@ -70,26 +70,31 @@ import jdk.test.lib.process.OutputAnalyzer; public class SharedBaseAddress { - // shared base address test table - private static final String[] testTable = { - "1g", "8g", "64g","512g", "4t", - "32t", "128t", "0", + // shared base address test table for {32, 64}bit VM + private static final String[] testTableShared = { + "1g", "0", "1", "64k", "64M", + "0xfff80000", // archive top wraps around 32-bit address space + "0xffffffff", // archive bottom wraps around 32-bit address space -- due to align_up() + "0" // always let OS pick the base address at runtime (ASLR for CDS archive) + }; + + // shared base address test table for 64bit VM only + private static final String[] testTable64 = { + "8g", "64g","512g", "4t", + "32t", "128t", "0x800001000", // Default base address + 1 page - probably valid but unaligned to metaspace alignment, see JDK 8247522 "0xfffffffffff00000", // archive top wraps around 64-bit address space - "0xfff80000", // archive top wraps around 32-bit address space "0xffffffffffffffff", // archive bottom wraps around 64-bit address space -- due to align_up() - "0xffffffff", // archive bottom wraps around 32-bit address space -- due to align_up() "0x00007ffffff00000", // end of archive will go past the end of user space on linux/x64 - "0x500000000", // (20g) below 32g at a 4g aligned address, but cannot be expressed with a logical + "0x500000000" // (20g) below 32g at a 4g aligned address, but cannot be expressed with a logical // immediate on aarch64 (0x5_0000_0000) (see JDK-8265705) - "0", // always let OS pick the base address at runtime (ASLR for CDS archive) }; // failed pattern private static String failedPattern = "os::release_memory\\(0x[0-9a-fA-F]*,\\s[0-9]*\\)\\sfailed"; - public static void main(String[] args) throws Exception { + public static void test(String[] args, String[] testTable) throws Exception { int mid = testTable.length / 2; int start = args[0].equals("0") ? 0 : mid; int end = args[0].equals("0") ? mid : testTable.length; @@ -134,4 +139,11 @@ public class SharedBaseAddress { } } } + + public static void main(String[] args) throws Exception { + test(args, testTableShared); + if (Platform.is64bit()) { + test(args, testTable64); + } + } } diff --git a/test/hotspot/jtreg/runtime/cds/appcds/SharedBaseAddress.java b/test/hotspot/jtreg/runtime/cds/appcds/SharedBaseAddress.java index 5d981c017944c05890d6d33951b77caafd6fe415..2220fc52baabaea7e8bf0258f8608221a7cef3f9 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/SharedBaseAddress.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/SharedBaseAddress.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 @@ -33,19 +33,24 @@ * @run main/timeout=240 SharedBaseAddress */ +import jdk.test.lib.Platform; import jdk.test.lib.process.OutputAnalyzer; public class SharedBaseAddress { - // shared base address test table - private static final String[] testTable = { - "1g", "8g", "64g","512g", "4t", - "32t", "128t", "0", - "1", "64k", "64M", "320g", + // shared base address test table for {32, 64}bit VM + private static final String[] testTableShared = { + "1g", "0", "1", "64k", "64M" + }; + + // shared base address test table for 64bit VM only + private static final String[] testTable64 = { + "8g", "64g","512g", "4t", + "32t", "128t", "320g", "0x800001000" // Default base address + 1 page - probably valid but unaligned to metaspace alignment, see JDK 8247522 }; - public static void main(String[] args) throws Exception { + public static void test(String[] testTable) throws Exception { String appJar = JarBuilder.getOrCreateHelloJar(); for (String testEntry : testTable) { @@ -62,4 +67,11 @@ public class SharedBaseAddress { TestCommon.checkExec(execOutput, "Hello World"); } } + + public static void main(String[] args) throws Exception { + test(testTableShared); + if (Platform.is64bit()) { + test(testTable64); + } + } } diff --git a/test/hotspot/jtreg/runtime/cds/appcds/TestCommon.java b/test/hotspot/jtreg/runtime/cds/appcds/TestCommon.java index 959d43173d0f8da35a74072dbb0b8e19aa23158b..55c10299ed6a437f454b0925dea2d8d643017d70 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/TestCommon.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/TestCommon.java @@ -466,7 +466,7 @@ public class TestCommon extends CDSTestUtils { public static Result runWithoutCDS(String... suffix) throws Exception { AppCDSOptions opts = (new AppCDSOptions()); - opts.addSuffix(suffix).setXShareMode("off");; + opts.addSuffix(suffix).setXShareMode("off"); return new Result(opts, runWithArchive(opts)); } diff --git a/test/hotspot/jtreg/runtime/cds/appcds/TestParallelGCWithCDS.java b/test/hotspot/jtreg/runtime/cds/appcds/TestParallelGCWithCDS.java new file mode 100644 index 0000000000000000000000000000000000000000..dd3f0fdcd564214bd551e91b59f2ea83b194afcd --- /dev/null +++ b/test/hotspot/jtreg/runtime/cds/appcds/TestParallelGCWithCDS.java @@ -0,0 +1,128 @@ +/* + * 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 Loading CDS archived heap objects into ParallelGC + * @bug 8274788 + * @requires vm.cds + * @requires vm.gc.Parallel + * @requires vm.gc.G1 + * + * @comment don't run this test if any -XX::+Use???GC options are specified, since they will + * interfere with the the test. + * @requires vm.gc == null + * + * @library /test/lib /test/hotspot/jtreg/runtime/cds/appcds + * @compile test-classes/Hello.java + * @run driver TestParallelGCWithCDS + */ + +import jdk.test.lib.Platform; +import jdk.test.lib.process.OutputAnalyzer; + +public class TestParallelGCWithCDS { + public final static String HELLO = "Hello World"; + static String helloJar; + + public static void main(String... args) throws Exception { + helloJar = JarBuilder.build("hello", "Hello"); + + // Check if we can use ParallelGC during dump time, or run time, or both. + test(false, true); + test(true, false); + test(true, true); + + // With G1 we usually have 2 heap regions. To increase test coverage, we can have 3 heap regions + // by using "-Xmx256m -XX:ObjectAlignmentInBytes=64" + if (Platform.is64bit()) test(false, true, true); + } + + final static String G1 = "-XX:+UseG1GC"; + final static String Parallel = "-XX:+UseParallelGC"; + + static void test(boolean dumpWithParallel, boolean execWithParallel) throws Exception { + test(dumpWithParallel, execWithParallel, false); + } + + static void test(boolean dumpWithParallel, boolean execWithParallel, boolean useSmallRegions) throws Exception { + String dumpGC = dumpWithParallel ? Parallel : G1; + String execGC = execWithParallel ? Parallel : G1; + String small1 = useSmallRegions ? "-Xmx256m" : "-showversion"; + String small2 = useSmallRegions ? "-XX:ObjectAlignmentInBytes=64" : "-showversion"; + OutputAnalyzer out; + + System.out.println("0. Dump with " + dumpGC); + out = TestCommon.dump(helloJar, + new String[] {"Hello"}, + dumpGC, + small1, + small2, + "-Xlog:cds"); + out.shouldContain("Dumping shared data to file:"); + out.shouldHaveExitValue(0); + + System.out.println("1. Exec with " + execGC); + out = TestCommon.exec(helloJar, + execGC, + small1, + small2, + "-Xlog:cds", + "Hello"); + out.shouldContain(HELLO); + out.shouldHaveExitValue(0); + + int n = 2; + if (!dumpWithParallel && execWithParallel) { + // We dumped with G1, so we have an archived heap. At exec time, try to load them into + // a small ParallelGC heap that may be too small. + String[] sizes = { + "4m", // usually this will success load the archived heap + "2m", // usually this will fail to load the archived heap, but app can launch + // or fail with "GC triggered before VM initialization completed" + "1m" // usually this will cause VM launch to fail with "Too small maximum heap" + }; + for (String sz : sizes) { + String xmx = "-Xmx" + sz; + System.out.println("=======\n" + n + ". Exec with " + execGC + " " + xmx); + out = TestCommon.exec(helloJar, + execGC, + small1, + small2, + xmx, + "-Xlog:cds", + "Hello"); + if (out.getExitValue() == 0) { + out.shouldContain(HELLO); + } else { + String output = out.getStdout() + out.getStderr(); + String exp1 = "Too small maximum heap"; + String exp2 = "GC triggered before VM initialization completed"; + if (!output.contains(exp1) && !output.contains(exp2)) { + throw new RuntimeException("Either '" + exp1 + "' or '" + exp2 + "' must be in stdout/stderr \n"); + } + } + n++; + } + } + } +} diff --git a/test/hotspot/jtreg/runtime/cds/appcds/cacheObject/ArchivedEnumApp.java b/test/hotspot/jtreg/runtime/cds/appcds/cacheObject/ArchivedEnumApp.java new file mode 100644 index 0000000000000000000000000000000000000000..293bf726572cabe8b95cd770e1d41bedf604e91a --- /dev/null +++ b/test/hotspot/jtreg/runtime/cds/appcds/cacheObject/ArchivedEnumApp.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.lang.module.ModuleDescriptor; +import java.lang.module.ModuleDescriptor.Requires; +import java.lang.module.ModuleDescriptor.Requires.Modifier; +import java.util.Optional; + +public class ArchivedEnumApp { + public static void main(final String[] args) throws Exception { + // Validate the archiving of the synthetic Modifier.$VALUES field: + for (Modifier mod : Modifier.values()) { + check(mod); + } + if (Modifier.values().length != 4) { + throw new RuntimeException("Modifier.$VALUES.length expeced: 4, actual: " + Modifier.values().length); + } + + // All 4 enums must exist in synthetic Modifier.$VALUES + check_in_array(Modifier.MANDATED); + check_in_array(Modifier.STATIC); + check_in_array(Modifier.SYNTHETIC); + check_in_array(Modifier.TRANSITIVE); + + // Find this module from (archived) boot layer + String moduleName = "java.management"; + Optional module = ModuleLayer.boot().findModule(moduleName); + if (module.isEmpty()) { + throw new RuntimeException(moduleName + " module is missing in boot layer"); + } + ModuleDescriptor md = module.get().getDescriptor(); + System.out.println("Module: " + md); + for (Requires r : md.requires()) { + System.out.println("Requires: " + r); + for (Modifier mod : r.modifiers()) { + System.out.println(" modifier: " + mod); + check(mod); + } + } + + System.out.println("Success"); + } + + static void check(Modifier mod) { + // The archived Enum object must equal to one of the following + // four values. + if (mod != Modifier.MANDATED && + mod != Modifier.STATIC && + mod != Modifier.SYNTHETIC && + mod != Modifier.TRANSITIVE) { + + System.out.println("mod = " + info(mod)); + System.out.println("Modifier.MANDATED = " + info(Modifier.MANDATED)); + System.out.println("Modifier.STATIC = " + info(Modifier.STATIC)); + System.out.println("Modifier.SYNTHETIC = " + info(Modifier.SYNTHETIC)); + System.out.println("Modifier.TRANSITIVE = " + info(Modifier.TRANSITIVE)); + + throw new RuntimeException("Archived enum object does not match static fields in enum class: " + info(mod)); + } + } + + static void check_in_array(Modifier mod) { + for (Modifier m : Modifier.values()) { + if (mod == m) { + return; + } + } + throw new RuntimeException("Enum object is not in $VALUES array: " + info(mod)); + } + + static String info(Object o) { + return "@0x" + Integer.toHexString(System.identityHashCode(o)) + " " + o; + } +} diff --git a/test/hotspot/jtreg/runtime/cds/appcds/cacheObject/ArchivedEnumTest.java b/test/hotspot/jtreg/runtime/cds/appcds/cacheObject/ArchivedEnumTest.java new file mode 100644 index 0000000000000000000000000000000000000000..ec1bd213834a9a7af2987ae95a73681d6b43183a --- /dev/null +++ b/test/hotspot/jtreg/runtime/cds/appcds/cacheObject/ArchivedEnumTest.java @@ -0,0 +1,56 @@ +/* + * 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 8275731 + * @summary Enum objects that are stored in the archived module graph should match + * the static final fields in the Enum class. + * @modules java.management + * @requires vm.cds.write.archived.java.heap + * @library /test/lib /test/hotspot/jtreg/runtime/cds/appcds + * @build ArchivedEnumApp + * @run driver jdk.test.lib.helpers.ClassFileInstaller -jar ArchivedEnumApp.jar ArchivedEnumApp + * @run driver ArchivedEnumTest + */ + +import jdk.test.lib.helpers.ClassFileInstaller; +import jdk.test.lib.process.OutputAnalyzer; + +public class ArchivedEnumTest { + public static void main(String[] args) throws Exception { + String appJar = ClassFileInstaller.getJarPath("ArchivedEnumApp.jar"); + + OutputAnalyzer out = TestCommon.testDump(appJar, + TestCommon.list("ArchivedEnumApp")); + // Note: You can get the following line to fail by commenting out + // the ADD_EXCL(...) lines in cdsHeapVerifier.cpp + out.shouldNotContain("object points to a static field that may be reinitialized at runtime"); + + TestCommon.run("-cp", appJar, + "-Xlog:cds=debug", + "-Xlog:cds+heap", + "ArchivedEnumApp").assertNormalExit("Success"); + } +} diff --git a/test/hotspot/jtreg/runtime/cds/appcds/customLoader/SameNameInTwoLoadersTest.java b/test/hotspot/jtreg/runtime/cds/appcds/customLoader/SameNameInTwoLoadersTest.java index 72d62c64179afe4a76ceea0f9d1b548e7c6b9622..2aeb2d41559017de8a974aafc451403fe5812127 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/customLoader/SameNameInTwoLoadersTest.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/customLoader/SameNameInTwoLoadersTest.java @@ -54,7 +54,7 @@ public class SameNameInTwoLoadersTest { customJar = JarBuilder.build("SameNameInTwoLoadersTest_custom", "CustomLoadee", "CustomLoadee3"); useWbParam = "-Xbootclasspath/a:" + - JarBuilder.build(true, "WhiteBox", "sun/hotspot/WhiteBox");; + JarBuilder.build(true, "WhiteBox", "sun/hotspot/WhiteBox"); // ====== unrelated loaders executeTestCase(getClassList_FP(), diff --git a/test/hotspot/jtreg/runtime/cds/appcds/javaldr/LockDuringDump.java b/test/hotspot/jtreg/runtime/cds/appcds/javaldr/LockDuringDump.java index 04652d2eb782a8f3a943b1e626d0383099f9ad02..391596160d6b65b530357af9fc106c508d793181 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/javaldr/LockDuringDump.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/javaldr/LockDuringDump.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 @@ -68,7 +68,7 @@ public class LockDuringDump { TestCommon.testDump(appJar, TestCommon.list(LockDuringDumpApp.class.getName()), "-XX:+UnlockDiagnosticVMOptions", agentArg, agentArg2); - if (i != 0) { + if (i != 0 && !out.getStdout().contains("LockDuringDumpAgent timeout")) { out.shouldContain("Let's hold the lock on the literal string"); } diff --git a/test/hotspot/jtreg/runtime/cds/appcds/javaldr/LockDuringDumpAgent.java b/test/hotspot/jtreg/runtime/cds/appcds/javaldr/LockDuringDumpAgent.java index 5e053d83efcf03158575d4db66cf6f31b9e9abd7..57db61e9335c2d19cdb8f62c2b2086aba2ba1312 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/javaldr/LockDuringDumpAgent.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/javaldr/LockDuringDumpAgent.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 @@ -51,9 +51,21 @@ public class LockDuringDumpAgent implements Runnable { static void waitForThreadStart() { try { + long started = System.currentTimeMillis(); + long timeout = 10000; + synchronized (LITERAL) { + Thread.sleep(1); + } synchronized (lock) { while (!threadStarted) { - lock.wait(); + lock.wait(timeout); + long elapsed = System.currentTimeMillis() - started; + if (elapsed >= timeout) { + System.out.println("This JVM may decide to not launch any Java threads during -Xshare:dump."); + System.out.println("This is OK because no string objects could be in a locked state during heap dump."); + System.out.println("LockDuringDumpAgent timeout after " + elapsed + " ms"); + return; + } } System.out.println("Thread has started"); } diff --git a/test/hotspot/jtreg/runtime/exceptionMsgs/AbstractMethodError/AbstractMethodErrorTest.java b/test/hotspot/jtreg/runtime/exceptionMsgs/AbstractMethodError/AbstractMethodErrorTest.java index e576de4e81f0047fe0572e03158a4b9222a5c342..5c88f1722f52e40fe5c5ef7a7610e6846f4245a2 100644 --- a/test/hotspot/jtreg/runtime/exceptionMsgs/AbstractMethodError/AbstractMethodErrorTest.java +++ b/test/hotspot/jtreg/runtime/exceptionMsgs/AbstractMethodError/AbstractMethodErrorTest.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. * Copyright (c) 2018 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -26,6 +26,7 @@ * @test * @summary Check that the verbose message of the AME is printed correctly. * @requires !(os.arch=="arm") & vm.flavor == "server" & !vm.emulatedClient & vm.compMode=="Xmixed" & !vm.graal.enabled & vm.opt.UseJVMCICompiler != true & (vm.opt.TieredStopAtLevel == null | vm.opt.TieredStopAtLevel==4) + * @requires vm.opt.DeoptimizeALot != true * @library /test/lib / * @build sun.hotspot.WhiteBox * @run driver jdk.test.lib.helpers.ClassFileInstaller sun.hotspot.WhiteBox @@ -502,7 +503,7 @@ public class AbstractMethodErrorTest { // ------------------------------------------------------------------------- // This error should be detected interpreted. // -// Class hierachy: +// Class hierarchy: // // C // interface, defines aFunctionOfMyInterface() // | @@ -618,7 +619,7 @@ class AME1_E extends AME1_B implements AME1_C { // ------------------------------------------------------------------------- // This error should be detected interpreted. // -// Class hierachy: +// Class hierarchy: // // A // an interface declaring aFunctionOfMyInterface() // | @@ -664,7 +665,7 @@ class AME2_C extends AME2_B { // ----------------------------------------------------------------------- // Test AbstractMethod error shadowing existing implementation. // -// Class hierachy: +// Class hierarchy: // // A // a class implementing m() // | @@ -693,7 +694,7 @@ class AME3_C extends AME3_B { // Test AbstractMethod error shadowing existing implementation. In // this test there are several subclasses of the abstract class. // -// Class hierachy: +// Class hierarchy: // // A // A: a class implementing ma() // | @@ -733,7 +734,7 @@ class AME4_E extends AME4_B { // ------------------------------------------------------------------------- // This error should be detected while processing the vtable stub. // -// Class hierachy: +// Class hierarchy: // // A__ // abstract // /|\ \ @@ -811,7 +812,7 @@ class AME5_E extends AME5_A { // Test AbstractMethod error detected while processing // the itable stub. // -// Class hierachy: +// Class hierarchy: // // A__ (interface) // /|\ \ diff --git a/test/hotspot/jtreg/runtime/exceptionMsgs/IncompatibleClassChangeError/IncompatibleClassChangeErrorTest.java b/test/hotspot/jtreg/runtime/exceptionMsgs/IncompatibleClassChangeError/IncompatibleClassChangeErrorTest.java index dbeae9efce27483608c960c044eaa82f662aab32..179d7164241bf30cb563bdf9822172aaa5047668 100644 --- a/test/hotspot/jtreg/runtime/exceptionMsgs/IncompatibleClassChangeError/IncompatibleClassChangeErrorTest.java +++ b/test/hotspot/jtreg/runtime/exceptionMsgs/IncompatibleClassChangeError/IncompatibleClassChangeErrorTest.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. * Copyright (c) 2018 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -345,7 +345,7 @@ class ImplementsSomeInterfaces extends // Helper classes to test incompatible class change in itable stub. // -// Class hierachy: +// Class hierarchy: // // iA,iB (interfaces) // /|\ \ @@ -407,7 +407,7 @@ class ICC2_E implements ICC2_iA, ICC2_iB { // Helper classes to test error where class appears in implements statement. // -// Class hierachy: +// Class hierarchy: // // A Some Class. // | @@ -421,7 +421,7 @@ class ICC3_B extends ICC3_A { // Helper classes to test error where interface appears in extends statement. // -// Class hierachy: +// Class hierarchy: // // A Some Interface. // | diff --git a/test/hotspot/jtreg/runtime/exceptionMsgs/methodPrinting/TestPrintingMethods.java b/test/hotspot/jtreg/runtime/exceptionMsgs/methodPrinting/TestPrintingMethods.java index 5c413b07a69ef8e294de2b73a3bbe9d349de32f6..dbd089c5dc0649e8affb4c14f04ecd7c2a85bbbc 100644 --- a/test/hotspot/jtreg/runtime/exceptionMsgs/methodPrinting/TestPrintingMethods.java +++ b/test/hotspot/jtreg/runtime/exceptionMsgs/methodPrinting/TestPrintingMethods.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. * Copyright (c) 2019 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -101,7 +101,7 @@ public class TestPrintingMethods { // ----------------------------------------------------------------------- // Test AbstractMethod error shadowing existing implementation. // -// Class hierachy: +// Class hierarchy: // // A // A class implementing m() and similar. // | diff --git a/test/hotspot/jtreg/serviceability/HeapDump/DuplicateArrayClassesTest.java b/test/hotspot/jtreg/serviceability/HeapDump/DuplicateArrayClassesTest.java new file mode 100644 index 0000000000000000000000000000000000000000..50a3441a609ca75ef3c6716f441be25abd384bb1 --- /dev/null +++ b/test/hotspot/jtreg/serviceability/HeapDump/DuplicateArrayClassesTest.java @@ -0,0 +1,336 @@ +/* + * 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.BufferedInputStream; +import java.io.EOFException; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.lang.ref.Reference; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Hashtable; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.TimeUnit; + +import jdk.test.lib.Asserts; +import jdk.test.lib.JDKToolLauncher; +import jdk.test.lib.apps.LingeredApp; +import jdk.test.lib.hprof.parser.PositionDataInputStream; +import jdk.test.lib.process.ProcessTools; + +/** + * @test + * @bug 8281267 + * @summary Verifies heap dump does not contain duplicate array classes + * @library /test/lib + * @run driver DuplicateArrayClassesTest + */ + +class DuplicateArrayClassesTarg extends LingeredApp { + public static void main(String[] args) { + // Initialize some array classes (for primitive type and object type). + int[][][] intArray = new int[0][][]; + String[][][] strArray = new String[0][][]; + LingeredApp.main(args); + Reference.reachabilityFence(intArray); + Reference.reachabilityFence(strArray); + } +} + + +public class DuplicateArrayClassesTest { + + public static void main(String[] args) throws Exception { + File dumpFile = new File("Myheapdump.hprof"); + createDump(dumpFile); + verifyDump(dumpFile); + } + + private static void createDump(File dumpFile) throws Exception { + LingeredApp theApp = null; + try { + theApp = new DuplicateArrayClassesTarg(); + + LingeredApp.startApp(theApp); + + //jcmd GC.heap_dump + JDKToolLauncher launcher = JDKToolLauncher + .createUsingTestJDK("jcmd") + .addToolArg(Long.toString(theApp.getPid())) + .addToolArg("GC.heap_dump") + .addToolArg(dumpFile.getAbsolutePath()); + Process p = ProcessTools.startProcess("jcmd", new ProcessBuilder(launcher.getCommand())); + // If something goes wrong with heap dumping most likely we'll get crash of the target VM. + while (!p.waitFor(5, TimeUnit.SECONDS)) { + if (!theApp.getProcess().isAlive()) { + log("ERROR: target VM died, killing jcmd..."); + p.destroyForcibly(); + throw new Exception("Target VM died"); + } + } + + if (p.exitValue() != 0) { + throw new Exception("Jcmd exited with code " + p.exitValue()); + } + } finally { + LingeredApp.stopApp(theApp); + } + } + + private static final byte HPROF_UTF8 = 0x01; + private static final byte HPROF_LOAD_CLASS = 0x02; + private static final byte HPROF_HEAP_DUMP = 0x0c; + private static final byte HPROF_GC_CLASS_DUMP = 0x20; + private static final byte HPROF_HEAP_DUMP_SEGMENT = 0x1C; + private static final byte HPROF_HEAP_DUMP_END = 0x2C; + + private static void verifyDump(File dumpFile) throws IOException { + Asserts.assertTrue(dumpFile.exists(), "Heap dump file not found."); + + // HPROF_UTF8 records. + Map names = new HashMap<>(); + // Maps from HPROF_LOAD_CLASS records. + Map classId2Name = new Hashtable<>(); + Map className2Id = new Hashtable<>(); + // Duplicate HPROF_LOAD_CLASS records. + List duplicateLoadClassIDs = new LinkedList<>(); + // HPROF_GC_CLASS_DUMP records. + Set dumpClassIDs = new HashSet<>(); + // Duplicate HPROF_GC_CLASS_DUMP records. + List duplicateDumpClassIDs = new LinkedList<>(); + + try (DumpInputStream in = new DumpInputStream(dumpFile)) { + while (true) { + DumpRecord rec; + try { + rec = in.readRecord(); + } catch (EOFException ex) { + break; + } + long pos = in.position(); // save the current pos + + switch (rec.tag()) { + case HPROF_UTF8: + long id = in.readID(); + byte[] chars = new byte[(int) rec.size - in.idSize]; + in.readFully(chars); + names.put(id, new String(chars)); + break; + case HPROF_LOAD_CLASS: + long classSerialNo = in.readU4(); + long classID = in.readID(); + long stackTraceSerialNo = in.readU4(); + long classNameID = in.readID(); + // We expect all names are dumped before classes. + String className = names.get(classNameID); + + String prevName = classId2Name.putIfAbsent(classID, className); + if (prevName != null) { // there is a class with the same ID + if (!prevName.equals(className)) { + // Something is completely wrong. + throw new RuntimeException("Found new class with id=" + classID + + " and different name (" + className + ", was " + prevName + ")"); + } + duplicateLoadClassIDs.add(classID); + } + // It's ok if we have other class with the same name (may be from other classloader). + className2Id.putIfAbsent(className, classID); + break; + case HPROF_HEAP_DUMP: + case HPROF_HEAP_DUMP_SEGMENT: + // HPROF_GC_CLASS_DUMP records are dumped first (in the beginning of the dump). + long endOfRecordPos = pos + rec.size(); + + while (in.position() < endOfRecordPos) { + byte subTag = in.readU1(); + if (subTag != HPROF_GC_CLASS_DUMP) { + break; + } + // We don't know HPROF_GC_CLASS_DUMP size, so have to read it completely. + long dumpClassID = readClassDump(in); + + if (!dumpClassIDs.add(dumpClassID)) { + duplicateDumpClassIDs.add(dumpClassID); + } + } + break; + } + + // Skip bytes till end of the record. + long bytesRead = in.position() - pos; + if (bytesRead > rec.size()) { + throw new RuntimeException("Bad record," + + " record.size = " + rec.size() + ", read " + bytesRead); + } + in.skipNBytes(rec.size() - bytesRead); + } + + log("HPROF_LOAD_CLASS records: " + (classId2Name.size() + duplicateLoadClassIDs.size())); + log("HPROF_GC_CLASS_DUMP records: " + (dumpClassIDs.size() + duplicateDumpClassIDs.size())); + + // Verify we have array classes used by target app. + String[] expectedClasses = {"[I", "[[I", "[[[I", + "[Ljava/lang/String;", "[[Ljava/lang/String;", "[[[Ljava/lang/String;"}; + for (String className: expectedClasses) { + Long classId = className2Id.get(className); + if (classId == null) { + throw new RuntimeException("no HPROF_LOAD_CLASS record for class " + className); + } + // verify there is HPROF_GC_CLASS_DUMP record for the class + if (!dumpClassIDs.contains(classId)) { + throw new RuntimeException("no HPROF_GC_CLASS_DUMP for class " + className); + } + log("found " + className); + } + if (!duplicateLoadClassIDs.isEmpty() || !duplicateDumpClassIDs.isEmpty()) { + log("Duplicate(s) detected:"); + log("HPROF_LOAD_CLASS records (" + duplicateLoadClassIDs.size() + "):"); + duplicateLoadClassIDs.forEach(id -> log(" - id = " + id + ": " + classId2Name.get(id))); + log("HPROF_GC_CLASS_DUMP records (" + duplicateDumpClassIDs.size() + "):"); + duplicateDumpClassIDs.forEach(id -> log(" - id = " + id + ": " + classId2Name.get(id))); + throw new RuntimeException("duplicates detected"); + } + } + } + + // Reads the whole HPROF_GC_CLASS_DUMP record, returns class ID. + private static long readClassDump(DumpInputStream in) throws IOException { + long classID = in.readID(); + long stackTraceNum = in.readU4(); + long superClassId = in.readID(); + long loaderClassId = in.readID(); + long signerClassId = in.readID(); + long protectionDomainClassId = in.readID(); + long reserved1 = in.readID(); + long reserved2 = in.readID(); + long instanceSize = in.readU4(); + long cpSize = in.readU2(); + for (long i = 0; i < cpSize; i++) { + long cpIndex = in.readU2(); + byte type = in.readU1(); + in.skipNBytes(in.type2size(type)); // value + } + long staticNum = in.readU2(); + for (long i = 0; i < staticNum; i++) { + long nameId = in.readID(); + byte type = in.readU1(); + in.skipNBytes(in.type2size(type)); // value + } + long instanceNum = in.readU2(); + for (long i = 0; i < instanceNum; i++) { + long nameId = in.readID(); + byte type = in.readU1(); + } + return classID; + } + + private static void log(Object s) { + System.out.println(s); + } + + + private static record DumpRecord (byte tag, long size) {} + + private static class DumpInputStream extends PositionDataInputStream { + public final int idSize; + + public DumpInputStream(File f) throws IOException { + super(new BufferedInputStream(new FileInputStream(f))); + + // read header: + // header "JAVA PROFILE 1.0.2" (0-terminated) + // u4 size of identifiers. Identifiers are used to represent + // u4 high word + // u4 low word number of milliseconds since 0:00 GMT, 1/1/70 + String header = readStr(); + log("header: \"" + header + "\""); + Asserts.assertTrue(header.startsWith("JAVA PROFILE ")); + + idSize = readInt(); + if (idSize != 4 && idSize != 8) { + Asserts.fail("id size " + idSize + " is not supported"); + } + // ignore timestamp + readU4(); + readU4(); + } + + // Reads null-terminated string + public String readStr() throws IOException { + StringBuilder sb = new StringBuilder(); + for (char ch = (char)readByte(); ch != '\0'; ch = (char)readByte()) { + sb.append(ch); + } + return sb.toString(); + } + + public byte readU1() throws IOException { + return readByte(); + } + public int readU2() throws IOException { + return readUnsignedShort(); + } + public long readU4() throws IOException { + // keep the value positive + return ((long)readInt() & 0x0FFFFFFFFL); + } + + public long readID() throws IOException { + return idSize == 4 ? readU4() : readLong(); + } + + public DumpRecord readRecord() throws IOException { + byte tag = readU1(); + readU4(); // timestamp, ignore it + long size = readU4(); + return new DumpRecord(tag, size); + } + + public long type2size(byte type) { + switch (type) { + case 1: // array + case 2: // object + return idSize; + case 4: // boolean + case 8: // byte + return 1; + case 5: // char + case 9: // short + return 2; + case 6: // float + case 10: // int + return 4; + case 7: // double + case 11: // long + return 8; + } + throw new RuntimeException("unknown type: " + type); + } + + } + +} diff --git a/test/hotspot/jtreg/serviceability/jvmti/Heap/IterateHeapWithEscapeAnalysisEnabled.java b/test/hotspot/jtreg/serviceability/jvmti/Heap/IterateHeapWithEscapeAnalysisEnabled.java index 03e388df6c38bd8878b71c79b746b00275831d41..6b835ca7ac823dd42dafc3c1f469827c6e0ed744 100644 --- a/test/hotspot/jtreg/serviceability/jvmti/Heap/IterateHeapWithEscapeAnalysisEnabled.java +++ b/test/hotspot/jtreg/serviceability/jvmti/Heap/IterateHeapWithEscapeAnalysisEnabled.java @@ -590,7 +590,7 @@ public class IterateHeapWithEscapeAnalysisEnabled { // The new instance is an ArgEscape instance and escapes to the JVMTI agent // while the target thread is in the call to dontinline_endlessLoop(). At this // location there is no local variable that references the ArgEscape. - ((ABBox) dontinline_endlessLoop(new ABBox(this))).synchronizedSlowInc();; + ((ABBox) dontinline_endlessLoop(new ABBox(this))).synchronizedSlowInc(); } } diff --git a/test/hotspot/jtreg/serviceability/jvmti/RedefineClasses/RedefineGenericSignatureTest.java b/test/hotspot/jtreg/serviceability/jvmti/RedefineClasses/RedefineGenericSignatureTest.java new file mode 100644 index 0000000000000000000000000000000000000000..b16120037e2a43dfad74c45534828ac9963e763a --- /dev/null +++ b/test/hotspot/jtreg/serviceability/jvmti/RedefineClasses/RedefineGenericSignatureTest.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 + * @bug 8282241 + * @summary Verifies class redefinition correctly updates generic_signature and source_file_name attributes + * @requires vm.jvmti + * @modules java.base/jdk.internal.org.objectweb.asm + * java.instrument + * @library /test/lib + * @run compile -g RedefineGenericSignatureTest.java + * @run main RedefineClassHelper + * @run main/othervm -javaagent:redefineagent.jar --add-opens=java.base/java.lang=ALL-UNNAMED RedefineGenericSignatureTest + */ + +import java.io.File; +import java.io.FileOutputStream; +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; +import java.lang.invoke.MethodType; +import java.lang.reflect.Type; +import java.nio.file.Files; +import java.util.List; + +import jdk.internal.org.objectweb.asm.ClassReader; +import jdk.internal.org.objectweb.asm.ClassVisitor; +import jdk.internal.org.objectweb.asm.ClassWriter; +import jdk.internal.org.objectweb.asm.Opcodes; +import jdk.test.lib.Asserts; +import jdk.test.lib.JDKToolLauncher; +import jdk.test.lib.compiler.InMemoryJavaCompiler; +import jdk.test.lib.process.ProcessTools; +import jdk.test.lib.process.OutputAnalyzer; + +class GenericSignatureTester { + public GenericSignatureTarget> method1() { + return null; + } +} + +class GenericSignatureTarget> { + public GenericSignatureTarget foo() { return null; } + public static void throwException() { throw new RuntimeException(); } +} + +public class RedefineGenericSignatureTest { + private static final String newTargetClassSource = + "class GenericSignatureTarget {\n" + + " public GenericSignatureTarget foo() { return null; }\n" + + " public static void throwException() { throw new RuntimeException(); }\n" + + "}\n"; + + public static void main (String[] args) throws Throwable { + RedefineGenericSignatureTest test = new RedefineGenericSignatureTest(); + test.runTest(); + } + + private final static String sourceFileName = "RedefineGenericSignatureTest.java"; + private final static String sourceFileNameNew = "RedefineGenericSignatureTestNew.java"; + // expected signature of GenericSignatureTester.method1 return type + private final static String expectedRetType = "GenericSignatureTarget>"; + // expected generic signature of the original GenericSignatureTarget + private final static String expectedSigOld = ";>Ljava/lang/Object;"; + // expected generic signature of the redefined GenericSignatureTarget + private final static String expectedSigNew = "Ljava/lang/Object;"; + + private static void log(Object o) { + System.out.println(o); + } + + private String getTargetGenSig() throws Throwable { + MethodHandles.Lookup lookup = MethodHandles.lookup(); + MethodHandles.Lookup classLookup = MethodHandles.privateLookupIn(Class.class, lookup); + MethodHandle getGenericSignature0 = classLookup.findVirtual( + Class.class, "getGenericSignature0", MethodType.methodType(String.class)); + Object genericSignature = getGenericSignature0.invoke(GenericSignatureTarget.class); + return String.valueOf(genericSignature); + } + + private String getTesterRetType() throws Throwable { + Type type = GenericSignatureTester.class.getDeclaredMethod("method1").getGenericReturnType(); + return String.valueOf(type); + } + + private String getTargetSourceFilename() { + try { + GenericSignatureTarget.throwException(); + } catch (RuntimeException ex) { + return ex.getStackTrace()[0].getFileName(); + } + return "Cannot get source file name"; + } + + // Prints dissassembled class bytes. + private void printDisassembled(String description, Class cls, byte[] bytes) throws Exception { + log(description + " -------------------"); + + File f = new File(cls.getSimpleName()+".class"); + try (FileOutputStream fos = new FileOutputStream(f)) { + fos.write(bytes); + } + JDKToolLauncher javap = JDKToolLauncher.create("javap") + .addToolArg("-verbose") + .addToolArg("-p") // Shows all classes and members. + //.addToolArg("-c") // Prints out disassembled code + .addToolArg("-s") // Prints internal type signatures. + .addToolArg(f.toString()); + ProcessBuilder pb = new ProcessBuilder(javap.getCommand()); + OutputAnalyzer out = ProcessTools.executeProcess(pb); + out.shouldHaveExitValue(0); + try { + Files.delete(f.toPath()); + } catch (Exception ex) { + // ignore + } + out.asLines().forEach(s -> log(s)); + log("=========================================="); + Files.deleteIfExists(f.toPath()); + } + + private byte[] getNewClassBytes() { + byte[] bytecode = InMemoryJavaCompiler.compile(GenericSignatureTarget.class.getName(), newTargetClassSource, "-g"); + + ClassWriter cw = new ClassWriter(0); + ClassReader cr = new ClassReader(bytecode); + cr.accept(new ClassVisitor(Opcodes.ASM7, cw) { + private boolean sourceSet = false; + @Override + public void visitSource(String source, String debug) { + sourceSet = true; + log("Changing source: \"" + source + "\" -> \"" + sourceFileNameNew + "\""); + super.visitSource(sourceFileNameNew, debug); + } + + @Override + public void visitEnd() { + if (!sourceSet) { + log("Set source: \"" + sourceFileNameNew + "\""); + super.visitSource(sourceFileNameNew, null); + } + super.visitEnd(); + } + }, 0); + return cw.toByteArray(); + } + + private void runTest() throws Throwable { + Class targetClass = GenericSignatureTarget.class; + + String oldSig = getTargetGenSig(); + log("old target class sig: \"" + oldSig + "\""); + + byte[] oldClassBytes = targetClass.getResourceAsStream(targetClass.getName() + ".class").readAllBytes(); + printDisassembled("Old " + targetClass.getName(), targetClass, oldClassBytes); + + log("Redefining " + targetClass.getName() + " class"); + byte[] newClassBytes = getNewClassBytes(); + printDisassembled("New " + targetClass.getName(), targetClass, newClassBytes); + RedefineClassHelper.redefineClass(targetClass, newClassBytes); + + String newSig = getTargetGenSig(); + log("new target class sig: \"" + newSig + "\""); + + String newRetType = getTesterRetType(); + log("new tester ret type: \"" + newRetType + "\""); + + String newSrcFileName = getTargetSourceFilename(); + log("new source file name: \"" + newSrcFileName + "\""); + + Asserts.assertStringsEqual(expectedSigOld, oldSig, "wrong old generic signature"); + Asserts.assertStringsEqual(expectedSigNew, newSig, "wrong new generic signature"); + Asserts.assertStringsEqual(expectedRetType, newRetType, "wrong ret type"); + Asserts.assertStringsEqual(sourceFileNameNew, newSrcFileName, "wrong new source file name"); + } +} diff --git a/test/hotspot/jtreg/serviceability/jvmti/SetBreakpoint/TestManyBreakpoints.java b/test/hotspot/jtreg/serviceability/jvmti/SetBreakpoint/TestManyBreakpoints.java new file mode 100644 index 0000000000000000000000000000000000000000..bc935ea99d19f619434f27417b0eeeab3debb14b --- /dev/null +++ b/test/hotspot/jtreg/serviceability/jvmti/SetBreakpoint/TestManyBreakpoints.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 8144992 + * @requires vm.jvmti + * @modules java.base/jdk.internal.org.objectweb.asm + * @run main/othervm/native -agentlib:TestManyBreakpoints + * -Xlog:gc+metaspace + * -Xint + * -XX:MetaspaceSize=16K -XX:MaxMetaspaceSize=64M + * TestManyBreakpoints + */ + +import jdk.internal.org.objectweb.asm.ClassWriter; +import jdk.internal.org.objectweb.asm.Label; +import jdk.internal.org.objectweb.asm.MethodVisitor; +import jdk.internal.org.objectweb.asm.Opcodes; + +public class TestManyBreakpoints { + + static final int BATCHES = 50; + static final int METHODS = 1000; + + public static void main(String[] args) throws Exception { + for (int c = 0; c < BATCHES; c++) { + System.out.println("Batch " + c); + TestClassLoader loader = new TestClassLoader(); + Class.forName("Target", true, loader); + } + } + + private static class TestClassLoader extends ClassLoader implements Opcodes { + static byte[] TARGET_BYTES = generateTarget(); + + private static byte[] generateTarget() { + ClassWriter cw = new ClassWriter(0); + + cw.visit(52, ACC_SUPER | ACC_PUBLIC, "Target", null, "java/lang/Object", null); + for (int m = 0; m < METHODS; m++) { + MethodVisitor mv = cw.visitMethod(ACC_PUBLIC | ACC_STATIC, "m" + m, "()V", null, null); + mv.visitCode(); + mv.visitInsn(RETURN); + mv.visitMaxs(0, 0); + mv.visitEnd(); + } + cw.visitEnd(); + return cw.toByteArray(); + } + + @Override + protected Class findClass(String name) throws ClassNotFoundException { + if (name.equals("Target")) { + return defineClass(name, TARGET_BYTES, 0, TARGET_BYTES.length); + } else { + return super.findClass(name); + } + } + } + +} diff --git a/test/hotspot/jtreg/serviceability/jvmti/SetBreakpoint/libTestManyBreakpoints.cpp b/test/hotspot/jtreg/serviceability/jvmti/SetBreakpoint/libTestManyBreakpoints.cpp new file mode 100644 index 0000000000000000000000000000000000000000..dcb8f87ddd7566dfc9bd0143301e28da93c59871 --- /dev/null +++ b/test/hotspot/jtreg/serviceability/jvmti/SetBreakpoint/libTestManyBreakpoints.cpp @@ -0,0 +1,111 @@ +/* + * 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 "jvmti.h" + +#define TARGET_CLASS_NAME "LTarget;" + +static jvmtiEnv *jvmti = NULL; + +static void +check_jvmti_status(JNIEnv* jni, jvmtiError err, const char* msg) { + if (err != JVMTI_ERROR_NONE) { + printf("check_jvmti_status: %s, JVMTI function returned error: %d\n", msg, err); + jni->FatalError(msg); + } +} + +void JNICALL classprepare(jvmtiEnv* jvmti_env, JNIEnv* jni_env, jthread thread, jclass klass) { + char* buf; + jvmtiError err; + + err = jvmti->GetClassSignature(klass, &buf, NULL); + check_jvmti_status(jni_env, err, "classprepare: GetClassSignature error"); + + if (strncmp(buf, TARGET_CLASS_NAME, strlen(TARGET_CLASS_NAME)) == 0) { + jint nMethods; + jmethodID* methods; + int i; + + err = jvmti->GetClassMethods(klass, &nMethods, &methods); + check_jvmti_status(jni_env, err, "classprepare: GetClassMethods error"); + printf("Setting breakpoints in %s\n", buf); + fflush(stdout); + for (i = 0; i < nMethods; i++) { + err = jvmti->SetBreakpoint(methods[i], 0); + check_jvmti_status(jni_env, err, "classprepare: SetBreakpoint error"); + } + } +} + + +void JNICALL breakpoint(jvmtiEnv* jvmti_env, JNIEnv* jni_env, jthread thread, jmethodID method, jlocation location) { + // Do nothing +} + +JNIEXPORT jint JNICALL Agent_OnLoad(JavaVM* vm, char* options, void* reserved) { + jvmtiCapabilities capa; + jvmtiEventCallbacks cbs; + jint err; + + err = vm->GetEnv((void**)&jvmti, JVMTI_VERSION_1_0); + if (err != JNI_OK) { + printf("Agent_OnLoad: GetEnv error\n"); + return JNI_ERR; + } + + memset(&capa, 0, sizeof(capa)); + capa.can_generate_breakpoint_events = 1; + capa.can_generate_single_step_events = 1; + err = jvmti->AddCapabilities(&capa); + if (err != JNI_OK) { + printf("Agent_OnLoad: AddCapabilities error\n"); + return JNI_ERR; + } + + memset(&cbs, 0, sizeof(cbs)); + cbs.ClassPrepare = classprepare; + cbs.Breakpoint = breakpoint; + err = jvmti->SetEventCallbacks(&cbs, sizeof(cbs)); + if (err != JNI_OK) { + printf("Agent_OnLoad: SetEventCallbacks error\n"); + return JNI_ERR; + } + + err = jvmti->SetEventNotificationMode(JVMTI_ENABLE, JVMTI_EVENT_CLASS_PREPARE, NULL); + if (err != JNI_OK) { + printf("Agent_OnLoad: SetEventNotificationMode CLASS_PREPARE error\n"); + return JNI_ERR; + } + + err = jvmti->SetEventNotificationMode(JVMTI_ENABLE, JVMTI_EVENT_BREAKPOINT, NULL); + if (err != JNI_OK) { + printf("Agent_OnLoad: SetEventNotificationMode BREAKPOINT error\n"); + return JNI_ERR; + } + + return JNI_OK; +} diff --git a/test/hotspot/jtreg/serviceability/sa/ClhsdbFindPC.java b/test/hotspot/jtreg/serviceability/sa/ClhsdbFindPC.java index bc1dd5a896361658791eb3dc2cd2577be903ed11..4e86d42e5e990bdb77242a6978509c42675617ca 100644 --- a/test/hotspot/jtreg/serviceability/sa/ClhsdbFindPC.java +++ b/test/hotspot/jtreg/serviceability/sa/ClhsdbFindPC.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 @@ -35,6 +35,7 @@ import jtreg.SkippedException; * @test id=xcomp-process * @bug 8193124 * @summary Test the clhsdb 'findpc' command with Xcomp on live process + * @requires vm.compMode != "Xcomp" * @requires vm.hasSA * @requires vm.compiler1.enabled * @requires vm.opt.DeoptimizeALot != true @@ -49,6 +50,7 @@ import jtreg.SkippedException; * @requires vm.compMode != "Xcomp" * @requires vm.hasSA * @requires vm.compiler1.enabled + * @requires vm.opt.DeoptimizeALot != true * @library /test/lib * @run main/othervm/timeout=480 ClhsdbFindPC true true */ @@ -59,7 +61,6 @@ import jtreg.SkippedException; * @summary Test the clhsdb 'findpc' command w/o Xcomp on live process * @requires vm.hasSA * @requires vm.compiler1.enabled - * @requires vm.opt.DeoptimizeALot != true * @library /test/lib * @run main/othervm/timeout=480 ClhsdbFindPC false false */ @@ -68,7 +69,6 @@ import jtreg.SkippedException; * @test id=no-xcomp-core * @bug 8193124 * @summary Test the clhsdb 'findpc' command w/o Xcomp on core file - * @requires vm.compMode != "Xcomp" * @requires vm.hasSA * @requires vm.compiler1.enabled * @library /test/lib diff --git a/test/hotspot/jtreg/serviceability/sa/ClhsdbVmStructsDump.java b/test/hotspot/jtreg/serviceability/sa/ClhsdbVmStructsDump.java index 680d9078d3bfcfb3d8feae542d7b44324455e2ef..050ec9c05d62b8ee82d9769d066931be0cd6f029 100644 --- a/test/hotspot/jtreg/serviceability/sa/ClhsdbVmStructsDump.java +++ b/test/hotspot/jtreg/serviceability/sa/ClhsdbVmStructsDump.java @@ -57,7 +57,7 @@ public class ClhsdbVmStructsDump { "field Klass _name Symbol*", "type ClassLoaderData* null", "field JavaThread _osthread OSThread*", - "type TenuredGeneration CardGeneration", + "type TenuredGeneration Generation", "type Universe null", "type ConstantPoolCache MetaspaceObj")); test.run(theApp.getPid(), cmds, expStrMap, null); diff --git a/test/hotspot/jtreg/serviceability/sa/TestType.java b/test/hotspot/jtreg/serviceability/sa/TestType.java index 1e4a9e56e575b9de43b59935862031cc96bc0ec4..4f71e42cd4e7c83eae6f2c03f24ea05bb5238fbc 100644 --- a/test/hotspot/jtreg/serviceability/sa/TestType.java +++ b/test/hotspot/jtreg/serviceability/sa/TestType.java @@ -62,7 +62,6 @@ public class TestType { "type ConstantPoolCache MetaspaceObj", "type ConstantPool Metadata", "type CompilerThread JavaThread", - "type CardGeneration Generation", "type ArrayKlass Klass", "type InstanceKlass Klass")); // String to check for in the output of "type InstanceKlass" diff --git a/test/hotspot/jtreg/testlibrary/ctw/src/sun/hotspot/tools/ctw/CtwRunner.java b/test/hotspot/jtreg/testlibrary/ctw/src/sun/hotspot/tools/ctw/CtwRunner.java index 187b86f6f3a1e078eff1b28b3bb03e3949429afc..2f0dca674270515806b7a4927d84fc899eafc811 100644 --- a/test/hotspot/jtreg/testlibrary/ctw/src/sun/hotspot/tools/ctw/CtwRunner.java +++ b/test/hotspot/jtreg/testlibrary/ctw/src/sun/hotspot/tools/ctw/CtwRunner.java @@ -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 @@ -93,7 +93,7 @@ public class CtwRunner { errors = new ArrayList<>(); if (start.endsWith("%") && stop.endsWith("%")) { - int startPercentage = Integer.parseInt(start.substring(0, start.length() - 1));; + int startPercentage = Integer.parseInt(start.substring(0, start.length() - 1)); int stopPercentage = Integer.parseInt(stop.substring(0, stop.length() - 1)); if (startPercentage < 0 || startPercentage > 100 || stopPercentage < 0 || stopPercentage > 100) { @@ -291,7 +291,7 @@ public class CtwRunner { "-XX:+StressIGVN", "-XX:+StressCCP", // StressSeed is uint - "-XX:StressSeed=" + Math.abs(rng.nextLong()), + "-XX:StressSeed=" + Math.abs(rng.nextInt()), // CTW entry point CompileTheWorld.class.getName(), target)); diff --git a/test/hotspot/jtreg/testlibrary_tests/ir_framework/examples/IRExample.java b/test/hotspot/jtreg/testlibrary_tests/ir_framework/examples/IRExample.java index 950cca3844fcae57d955eadac656460656fc0dad..9142d31307833a98dd141940f6647c0590cab368 100644 --- a/test/hotspot/jtreg/testlibrary_tests/ir_framework/examples/IRExample.java +++ b/test/hotspot/jtreg/testlibrary_tests/ir_framework/examples/IRExample.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 @@ -24,7 +24,7 @@ package ir_framework.examples; import compiler.lib.ir_framework.*; -import compiler.lib.ir_framework.driver.IRViolationException; +import compiler.lib.ir_framework.driver.irmatching.IRViolationException; /* * @test diff --git a/test/hotspot/jtreg/testlibrary_tests/ir_framework/tests/TestCheckedTests.java b/test/hotspot/jtreg/testlibrary_tests/ir_framework/tests/TestCheckedTests.java index 6a8d5c50c6acc0b89dc227329cbd1bcacb6e7ac6..c08635b14bc3cc008f09464c0e09e293a67eeebe 100644 --- a/test/hotspot/jtreg/testlibrary_tests/ir_framework/tests/TestCheckedTests.java +++ b/test/hotspot/jtreg/testlibrary_tests/ir_framework/tests/TestCheckedTests.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 @@ -24,7 +24,7 @@ package ir_framework.tests; import compiler.lib.ir_framework.*; -import compiler.lib.ir_framework.driver.IRViolationException; +import compiler.lib.ir_framework.driver.irmatching.IRViolationException; import compiler.lib.ir_framework.driver.TestVMException; import java.io.ByteArrayOutputStream; import java.io.PrintStream; diff --git a/test/hotspot/jtreg/testlibrary_tests/ir_framework/tests/TestCompileThreshold.java b/test/hotspot/jtreg/testlibrary_tests/ir_framework/tests/TestCompileThreshold.java index 76090b94efc746807558f37a5a85fd4fae71c5c8..145430f61f99b964825b4b31ee9e3d14e77f4f59 100644 --- a/test/hotspot/jtreg/testlibrary_tests/ir_framework/tests/TestCompileThreshold.java +++ b/test/hotspot/jtreg/testlibrary_tests/ir_framework/tests/TestCompileThreshold.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 @@ -24,7 +24,7 @@ package ir_framework.tests; import compiler.lib.ir_framework.*; -import compiler.lib.ir_framework.driver.IRViolationException; +import compiler.lib.ir_framework.driver.irmatching.IRViolationException; import jdk.test.lib.Asserts; /* diff --git a/test/hotspot/jtreg/testlibrary_tests/ir_framework/tests/TestIRMatching.java b/test/hotspot/jtreg/testlibrary_tests/ir_framework/tests/TestIRMatching.java index f4ce560d2f4d381d41761f44f07e57c6bcd8c2fd..c6c81d8c2042124706b646028aca262d424729e6 100644 --- a/test/hotspot/jtreg/testlibrary_tests/ir_framework/tests/TestIRMatching.java +++ b/test/hotspot/jtreg/testlibrary_tests/ir_framework/tests/TestIRMatching.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 @@ -24,7 +24,7 @@ package ir_framework.tests; import compiler.lib.ir_framework.*; -import compiler.lib.ir_framework.driver.IRViolationException; +import compiler.lib.ir_framework.driver.irmatching.IRViolationException; import jdk.test.lib.Asserts; import jdk.test.lib.Platform; import sun.hotspot.WhiteBox; @@ -60,7 +60,7 @@ public class TestIRMatching { private static void addException(Exception e) { System.out.flush(); System.err.flush(); - exceptions.put(e, baos.toString() + System.lineSeparator() + baosErr.toString()); + exceptions.put(e, baos + System.lineSeparator() + baosErr); } public static void main(String[] args) { @@ -285,20 +285,20 @@ public class TestIRMatching { runWithArguments(FlagComparisons.class, "-XX:TLABRefillWasteFraction=50"); System.out.flush(); String output = baos.toString(); - findIrIds(output, "testMatchAllIf50", 0, 21); + findIrIds(output, "testMatchAllIf50", 1, 22); findIrIds(output, "testMatchNoneIf50", -1, -1); runWithArguments(FlagComparisons.class, "-XX:TLABRefillWasteFraction=49"); System.out.flush(); output = baos.toString(); - findIrIds(output, "testMatchAllIf50", 4, 6, 13, 18); - findIrIds(output, "testMatchNoneIf50", 0, 3, 8, 10, 17, 22); + findIrIds(output, "testMatchAllIf50", 5, 7, 14, 19); + findIrIds(output, "testMatchNoneIf50", 1, 4, 9, 11, 18, 23); runWithArguments(FlagComparisons.class, "-XX:TLABRefillWasteFraction=51"); System.out.flush(); output = baos.toString(); - findIrIds(output, "testMatchAllIf50", 7, 12, 19, 21); - findIrIds(output, "testMatchNoneIf50", 4, 7, 11, 16, 20, 22); + findIrIds(output, "testMatchAllIf50", 8, 13, 20, 22); + findIrIds(output, "testMatchNoneIf50", 5, 8, 12, 17, 21, 23); System.setOut(oldOut); System.setErr(oldErr); @@ -395,7 +395,7 @@ public class TestIRMatching { } } if (!output.contains(builder.toString())) { - addException(new RuntimeException("Could not find encoding: \"" + builder.toString() + System.lineSeparator())); + addException(new RuntimeException("Could not find encoding: \"" + builder + System.lineSeparator())); } } } @@ -550,20 +550,20 @@ class MultipleFailOnBad { class FlagComparisons { // Applies all IR rules if TLABRefillWasteFraction=50 @Test - @IR(failOn = IRNode.CALL, applyIf = {"TLABRefillWasteFraction", "50"}) // Index 0 + @IR(failOn = IRNode.CALL, applyIf = {"TLABRefillWasteFraction", "50"}) // Index 1 @IR(failOn = IRNode.CALL, applyIf = {"TLABRefillWasteFraction", "=50"}) @IR(failOn = IRNode.CALL, applyIf = {"TLABRefillWasteFraction", "= 50"}) @IR(failOn = IRNode.CALL, applyIf = {"TLABRefillWasteFraction", " = 50"}) - @IR(failOn = IRNode.CALL, applyIf = {"TLABRefillWasteFraction", "<=50"}) // Index 4 + @IR(failOn = IRNode.CALL, applyIf = {"TLABRefillWasteFraction", "<=50"}) // Index 5 @IR(failOn = IRNode.CALL, applyIf = {"TLABRefillWasteFraction", "<= 50"}) @IR(failOn = IRNode.CALL, applyIf = {"TLABRefillWasteFraction", " <= 50"}) - @IR(failOn = IRNode.CALL, applyIf = {"TLABRefillWasteFraction", ">=50"}) // Index 7 + @IR(failOn = IRNode.CALL, applyIf = {"TLABRefillWasteFraction", ">=50"}) // Index 8 @IR(failOn = IRNode.CALL, applyIf = {"TLABRefillWasteFraction", ">= 50"}) @IR(failOn = IRNode.CALL, applyIf = {"TLABRefillWasteFraction", " >= 50"}) @IR(failOn = IRNode.CALL, applyIf = {"TLABRefillWasteFraction", ">49"}) @IR(failOn = IRNode.CALL, applyIf = {"TLABRefillWasteFraction", "> 49"}) @IR(failOn = IRNode.CALL, applyIf = {"TLABRefillWasteFraction", " > 49"}) - @IR(failOn = IRNode.CALL, applyIf = {"TLABRefillWasteFraction", "<51"}) // Index 13 + @IR(failOn = IRNode.CALL, applyIf = {"TLABRefillWasteFraction", "<51"}) // Index 14 @IR(failOn = IRNode.CALL, applyIf = {"TLABRefillWasteFraction", "< 51"}) @IR(failOn = IRNode.CALL, applyIf = {"TLABRefillWasteFraction", " < 51"}) @IR(failOn = IRNode.CALL, applyIf = {"TLABRefillWasteFraction", "!=51"}) @@ -571,34 +571,34 @@ class FlagComparisons { @IR(failOn = IRNode.CALL, applyIf = {"TLABRefillWasteFraction", " != 51"}) @IR(failOn = IRNode.CALL, applyIf = {"TLABRefillWasteFraction", "!=49"}) @IR(failOn = IRNode.CALL, applyIf = {"TLABRefillWasteFraction", "!= 49"}) - @IR(failOn = IRNode.CALL, applyIf = {"TLABRefillWasteFraction", " != 49"}) // Index 21 + @IR(failOn = IRNode.CALL, applyIf = {"TLABRefillWasteFraction", " != 49"}) // Index 22 public void testMatchAllIf50() {} // Applies no IR rules if TLABRefillWasteFraction=50 @Test - @IR(failOn = IRNode.CALL, applyIf = {"TLABRefillWasteFraction", "49"}) // Index 0 + @IR(failOn = IRNode.CALL, applyIf = {"TLABRefillWasteFraction", "49"}) // Index 1 @IR(failOn = IRNode.CALL, applyIf = {"TLABRefillWasteFraction", "=49"}) @IR(failOn = IRNode.CALL, applyIf = {"TLABRefillWasteFraction", "= 49"}) @IR(failOn = IRNode.CALL, applyIf = {"TLABRefillWasteFraction", " = 49"}) - @IR(failOn = IRNode.CALL, applyIf = {"TLABRefillWasteFraction", "51"}) // Index 4 + @IR(failOn = IRNode.CALL, applyIf = {"TLABRefillWasteFraction", "51"}) // Index 5 @IR(failOn = IRNode.CALL, applyIf = {"TLABRefillWasteFraction", "=51"}) @IR(failOn = IRNode.CALL, applyIf = {"TLABRefillWasteFraction", "= 51"}) @IR(failOn = IRNode.CALL, applyIf = {"TLABRefillWasteFraction", " = 51"}) - @IR(failOn = IRNode.CALL, applyIf = {"TLABRefillWasteFraction", "<=49"}) // Index 8 + @IR(failOn = IRNode.CALL, applyIf = {"TLABRefillWasteFraction", "<=49"}) // Index 9 @IR(failOn = IRNode.CALL, applyIf = {"TLABRefillWasteFraction", "<= 49"}) @IR(failOn = IRNode.CALL, applyIf = {"TLABRefillWasteFraction", " <= 49"}) - @IR(failOn = IRNode.CALL, applyIf = {"TLABRefillWasteFraction", ">=51"}) // Index 11 + @IR(failOn = IRNode.CALL, applyIf = {"TLABRefillWasteFraction", ">=51"}) // Index 12 @IR(failOn = IRNode.CALL, applyIf = {"TLABRefillWasteFraction", ">= 51"}) @IR(failOn = IRNode.CALL, applyIf = {"TLABRefillWasteFraction", " >= 51"}) @IR(failOn = IRNode.CALL, applyIf = {"TLABRefillWasteFraction", ">50"}) @IR(failOn = IRNode.CALL, applyIf = {"TLABRefillWasteFraction", "> 50"}) @IR(failOn = IRNode.CALL, applyIf = {"TLABRefillWasteFraction", " > 50"}) - @IR(failOn = IRNode.CALL, applyIf = {"TLABRefillWasteFraction", "<50"}) // Index 17 + @IR(failOn = IRNode.CALL, applyIf = {"TLABRefillWasteFraction", "<50"}) // Index 18 @IR(failOn = IRNode.CALL, applyIf = {"TLABRefillWasteFraction", "< 50"}) @IR(failOn = IRNode.CALL, applyIf = {"TLABRefillWasteFraction", " < 50"}) @IR(failOn = IRNode.CALL, applyIf = {"TLABRefillWasteFraction", "!=50"}) @IR(failOn = IRNode.CALL, applyIf = {"TLABRefillWasteFraction", "!= 50"}) - @IR(failOn = IRNode.CALL, applyIf = {"TLABRefillWasteFraction", " != 50"}) // Index 22 + @IR(failOn = IRNode.CALL, applyIf = {"TLABRefillWasteFraction", " != 50"}) // Index 23 public void testMatchNoneIf50() {} } @@ -814,14 +814,14 @@ class BadCount { int iFld; int result; @Test - @IR(counts = {IRNode.LOAD, "!= 1"}) + @IR(counts = {IRNode.LOAD, "!= 1"}) // fail @IR(counts = {IRNode.STORE, "> 0"}) public void bad1() { result = iFld; } @Test - @IR(counts = {IRNode.LOAD, "1"}) + @IR(counts = {IRNode.LOAD, "1"}) // fail @IR(counts = {IRNode.STORE, "< 1"}) public void bad2() { result = iFld; @@ -829,8 +829,8 @@ class BadCount { @Test - @IR(counts = {IRNode.LOAD, "0"}) - @IR(counts = {IRNode.STORE, " <= 0"}) + @IR(counts = {IRNode.LOAD, "0"}) // fail + @IR(counts = {IRNode.STORE, " <= 0"}) // fail public void bad3() { result = iFld; } @@ -1514,7 +1514,7 @@ abstract class Constraint { } } } - Asserts.assertTrue(matched, toString() + " should have been matched"); + Asserts.assertTrue(matched, this + " should have been matched"); } abstract protected void checkIRRule(String irRule); @@ -1732,7 +1732,7 @@ class BadCountsConstraint extends RegexConstraint { private static List getMatchesList(int foundCount, String[] matches, List strings) { List matchesList = new ArrayList<>(); - matchesList.add("but found " + foundCount); + matchesList.add("Failed comparison: [found] " + foundCount); if (matches != null) { matchesList.addAll(strings); } diff --git a/test/hotspot/jtreg/testlibrary_tests/ir_framework/tests/TestRunTests.java b/test/hotspot/jtreg/testlibrary_tests/ir_framework/tests/TestRunTests.java index 780075f50dded29eb2801434dba7d57baeb9e79e..d2c83edde7e8d3c0d0ca7fb38b743854f74f3818 100644 --- a/test/hotspot/jtreg/testlibrary_tests/ir_framework/tests/TestRunTests.java +++ b/test/hotspot/jtreg/testlibrary_tests/ir_framework/tests/TestRunTests.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 @@ -24,7 +24,7 @@ package ir_framework.tests; import compiler.lib.ir_framework.*; -import compiler.lib.ir_framework.driver.IRViolationException; +import compiler.lib.ir_framework.driver.irmatching.IRViolationException; import compiler.lib.ir_framework.shared.TestRunException; import jdk.test.lib.Asserts; diff --git a/test/hotspot/jtreg/testlibrary_tests/ir_framework/tests/Utils.java b/test/hotspot/jtreg/testlibrary_tests/ir_framework/tests/Utils.java index 2b4e76a680541bf593c75f64e67d0a47e4705607..10c104734570a9e10d4f1410fc0daa8c3c64ec76 100644 --- a/test/hotspot/jtreg/testlibrary_tests/ir_framework/tests/Utils.java +++ b/test/hotspot/jtreg/testlibrary_tests/ir_framework/tests/Utils.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 @@ -24,8 +24,7 @@ package ir_framework.tests; import compiler.lib.ir_framework.Scenario; -import compiler.lib.ir_framework.driver.IRMatcher; -import compiler.lib.ir_framework.driver.TestVMProcess; +import compiler.lib.ir_framework.driver.irmatching.IRMatcher; import jdk.test.lib.Asserts; import java.util.Arrays; diff --git a/test/hotspot/jtreg/vmTestbase/jit/series/series.java b/test/hotspot/jtreg/vmTestbase/jit/series/series.java index c17e24427f90a7bc6f0d470c8231a1600e54978d..eef54c2c81a11109f246601b7f40f2b101b2cf8e 100644 --- a/test/hotspot/jtreg/vmTestbase/jit/series/series.java +++ b/test/hotspot/jtreg/vmTestbase/jit/series/series.java @@ -192,7 +192,7 @@ fres); { series patObj = new series(); if (patObj.runit()!=0) - throw new TestFailure("Test failed.");; + throw new TestFailure("Test failed."); series.goldChecker.check(); } } diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdb/threadgroup/threadgroup002/threadgroup002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdb/threadgroup/threadgroup002/threadgroup002.java index cb8004643d3b7ec8232ed3d13def30043c0db52e..72bbf3584741d07130c3d4c9d1c9875e3667a3e0 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdb/threadgroup/threadgroup002/threadgroup002.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdb/threadgroup/threadgroup002/threadgroup002.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 @@ -29,11 +29,15 @@ * VM Testbase keywords: [jpda, jdb] * VM Testbase readme: * DECSRIPTION - * This is a test for jdb 'threadgroup ' command. + * This is a test for jdb 'threadgroup ' command and + * also for the 'threadgroup' command with no argument. * The main thread creates 3 threadgroups of 5 threads each. * All threads are locked in their 'run' method on a lock that the main - * thread holds. The test passes if jdb correctly switches between - * three user-defined threadgroups using 'threadgroup' command. + * thread holds. The test then makes sure jdb correctly switches between + * the three user-defined threadgroups using 'threadgroup' command. It then + * resets the current threadgroup back to the default top level threadgroup + * by using the 'threadgroup' command with no argument. It then tests that + * all 3 created threadgroups can be found in the 'threads' output. * COMMENTS * This test functionally equals to nsk/jdb/threadgroup/threadgroup001 * test and replaces it. @@ -45,6 +49,7 @@ * nsk.jdb.threadgroup.threadgroup002.threadgroup002 * -arch=${os.family}-${os.simpleArch} * -waittime=5 + * -verbose * -debugee.vmkind=java * -transport.address=dynamic * -jdb=${test.jdk}/bin/jdb @@ -100,6 +105,15 @@ public class threadgroup002 extends JdbTest { } } + // Test switching back to the default top level group. + reply = jdb.receiveReplyFor(JdbCommand.threadgroup); + reply = jdb.receiveReplyFor(JdbCommand.threads); + grep = new Paragrep(reply); + count = grep.find(threadgroup002a.THREADGROUP_NAME); + if (count != threadgroup002a.numThreadGroups) { + failure("jdb cannot switch to default top level threadgroup"); + } + jdb.contToExit(1); } } diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdb/unmonitor/unmonitor001/unmonitor001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdb/unmonitor/unmonitor001/unmonitor001.java index 54a90a930f277064826f54926000716264371238..9fe8a7e57035d34b51ebe466894c026e9bee9aba 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdb/unmonitor/unmonitor001/unmonitor001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdb/unmonitor/unmonitor001/unmonitor001.java @@ -172,7 +172,7 @@ public class unmonitor001 extends JdbTest { private boolean checkCommands(String[] reply) { Paragrep grep; String found; - Vector v = new Vector();; + Vector v = new Vector(); boolean result = true; int count; diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/multithrd/tc02x003.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/multithrd/tc02x003.java index 4fd48e21ff06ac70913a9fd55986ddd7cf7a1fab..79bb11fc70677ea36dfbd344263e340ab320b312 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/multithrd/tc02x003.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/BScenarios/multithrd/tc02x003.java @@ -146,7 +146,7 @@ public class tc02x003 { hitEvent(clsEvent); mthdReq = evm.createMethodEntryRequest(); - ReferenceType testedClass = clsEvent.referenceType();; + ReferenceType testedClass = clsEvent.referenceType(); mthdReq.addClassFilter(testedClass); mthdReq.enable(); diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassObjectReference/reflectedType/reflectype002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassObjectReference/reflectedType/reflectype002.java index da528cee5b30ec49e7508bbabf91de7d53e1fe5a..46608d9b07d85447a9db4bf76600f9f9aa15f54a 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassObjectReference/reflectedType/reflectype002.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassObjectReference/reflectedType/reflectype002.java @@ -166,7 +166,7 @@ public class reflectype002 extends Log { print_log_on_verbose ("--> reflectype002: getting ClassObjectReference object for loaded checked class..."); - ClassObjectReference class_obj_ref = refType.classObject();; + ClassObjectReference class_obj_ref = refType.classObject(); print_log_on_verbose("--> reflectype002: getting ClassObjectReference object - DONE!"); print_log_on_verbose diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/LocalVariable/isVisible/isvisible001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/LocalVariable/isVisible/isvisible001.java index 9d5dba92c757f8539672ed25f7da0b108846c0c4..5593aabe31b6caf9d5959f09ad6f48e0c74f399d 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/LocalVariable/isVisible/isvisible001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/LocalVariable/isVisible/isvisible001.java @@ -415,7 +415,7 @@ public class isvisible001 { expresult = returnCode1; } } catch ( IllegalArgumentException e ) { - log3("ERROR: IllegalArgumentException for i3 in stackFrame");; + log3("ERROR: IllegalArgumentException for i3 in stackFrame"); expresult = returnCode1; } } diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/frames/frames001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/frames/frames001.java index cc75403caf611e00127581d27824aa4604c6d67a..2e361e65cab007b50721daedee2a70e71f4c2935 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/frames/frames001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadReference/frames/frames001.java @@ -373,7 +373,7 @@ public class frames001 { log2(" getting new List of frames"); try { - frameList = thread2.frames();; + frameList = thread2.frames(); } catch ( IndexOutOfBoundsException e1 ) { log3("ERROR: IndexOutOfBoundsException"); expresult = returnCode1; diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/SuspendThread/suspendthrd003.java b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/SuspendThread/suspendthrd003.java index fd98b382d2a4a8898e342fa0480550b6633e6a67..e2a48a948e9c40050989b632682e10c5faf2be0c 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/SuspendThread/suspendthrd003.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/SuspendThread/suspendthrd003.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 @@ -88,6 +88,9 @@ public class suspendthrd003 extends DebugeeClass { int res = -1; long start_time = System.currentTimeMillis(); while (System.currentTimeMillis() < start_time + (timeMax * 1000)) { + // Start each loop with a clear log buffer so we only + // track the run that can potentially fail: + log.clearLogBuffer(); count++; // Original suspendthrd001 test block starts here: diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/scenarios/hotswap/HS201/hs201t002.java b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/scenarios/hotswap/HS201/hs201t002.java index e8a874f4c2758a4b1fbb2d2e0f059eb78f0c0457..c76a9b005d100efd194d306445910772db781dc9 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/scenarios/hotswap/HS201/hs201t002.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/scenarios/hotswap/HS201/hs201t002.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, 2018, 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 @@ -24,6 +24,7 @@ package nsk.jvmti.scenarios.hotswap.HS201; import java.io.PrintStream; +import java.util.concurrent.CountDownLatch; import nsk.share.*; import nsk.share.jvmti.*; @@ -73,14 +74,23 @@ public class hs201t002 extends DebugeeClass { timeout = argHandler.getWaitTime() * 60 * 1000; // milliseconds log.display(">>> starting tested thread"); - Thread thread = new hs201t002Thread(); + hs201t002Thread thread = new hs201t002Thread(); // testing sync status = checkStatus(status); - setThread(thread); thread.start(); + // setThread(thread) enables JVMTI events, and that can only be done on a live thread, + // so wait until the thread has started. + try { + thread.ready.await(); + } catch (InterruptedException e) { + } + setThread(thread); + + thread.go.countDown(); + while (currentStep != 4) { try { Thread.sleep(100); @@ -114,6 +124,10 @@ public class hs201t002 extends DebugeeClass { } log.display("Thread suspended in a wrong moment. Retrying..."); + for (int i = 0; i < stackTrace.length; i++) { + log.display("\t" + i + ". " + stackTrace[i]); + } + log.display("Retrying..."); resumeThread(thread); suspendTry++; // Test thread will be suspended at the top of the loop. Let it run for a while. @@ -136,12 +150,20 @@ public class hs201t002 extends DebugeeClass { class hs201t002Thread extends Thread { + CountDownLatch ready = new CountDownLatch(1); + CountDownLatch go = new CountDownLatch(1); + hs201t002Thread() { setName("hs201t002Thread"); } public void run() { // run method + ready.countDown(); + try { + go.await(); + } catch (InterruptedException e) { + } try { throwException(); } catch (Exception e) { diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/scenarios/hotswap/HS201/hs201t002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/scenarios/hotswap/HS201/hs201t002/TestDescription.java index e716d1b836c7648ce9151f6e3c6d3d162889c31f..07f9d2a6e9220343d382c88b4b4c3b30e19f9207 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/scenarios/hotswap/HS201/hs201t002/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/scenarios/hotswap/HS201/hs201t002/TestDescription.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 @@ -71,7 +71,7 @@ * newclass * * @run main/othervm/native - * -agentlib:hs201t002=pathToNewByteCode=./bin,-waittime=5 - * nsk.jvmti.scenarios.hotswap.HS201.hs201t002 + * -agentlib:hs201t002=pathToNewByteCode=./bin,-waittime=5,-verbose + * nsk.jvmti.scenarios.hotswap.HS201.hs201t002 -verbose */ diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/scenarios/hotswap/HS201/hs201t002/hs201t002.cpp b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/scenarios/hotswap/HS201/hs201t002/hs201t002.cpp index 29a8b7bbfa94e3994ee01257eaf9d42c77abf63d..8ceda496605aecc6dd43b7dc4e52482e9941631b 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/scenarios/hotswap/HS201/hs201t002/hs201t002.cpp +++ b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/scenarios/hotswap/HS201/hs201t002/hs201t002.cpp @@ -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 @@ -45,16 +45,18 @@ static jlong timeout = 0; #define PATH_TO_NEW_BYTECODE "pathToNewByteCode" static jint testStep; -static int redefineNumber; -static jint newClassSize; -static unsigned char* newClassBytes; static jthread testedThread; static jclass testClass; -char chbuffer[255]; -const char* getThreadName(JNIEnv* jni_env, jthread thread); +// callbackException (isCatch == false) and callbackExceptionCatch (isCatch == true) handler +void handleException(bool isCatch, + jvmtiEnv* jvmti_env, JNIEnv* jni_env, jthread thread, + jmethodID method, jlocation location, + jobject exception); + +const char* getThreadName(jvmtiEnv* jvmti_env, JNIEnv* jni_env, jthread thread); const char* getClassName(jvmtiEnv *jvmti_env, JNIEnv* jni_env, jobject object); -int readNewBytecode(jvmtiEnv* jvmti); +int readNewBytecode(jvmtiEnv* jvmti, jint *newClassSize, unsigned char* *newClassBytes); int getLocalVariableValue(jvmtiEnv *jvmti_env, jthread thread, jmethodID method); /* ============================================================================= */ @@ -99,17 +101,19 @@ void disableEvent(jvmtiEnv *jvmti_env, jvmtiEvent event, jthread thread) { void redefineClass(jvmtiEnv *jvmti_env, jclass klass) { jvmtiClassDefinition classDef; - char *className; + jint newClassSize; + unsigned char* newClassBytes; if (!NSK_JVMTI_VERIFY(jvmti_env->GetClassSignature(klass, &className, NULL))) { nsk_jvmti_setFailStatus(); return; } - if (!NSK_VERIFY(readNewBytecode(jvmti_env))) { + if (!NSK_VERIFY(readNewBytecode(jvmti_env, &newClassSize, &newClassBytes))) { NSK_COMPLAIN0("TEST FAILED: new bytecode could not be read\n"); nsk_jvmti_setFailStatus(); + jvmti_env->Deallocate((unsigned char*)className); return; } @@ -121,12 +125,14 @@ void redefineClass(jvmtiEnv *jvmti_env, jclass klass) { if (!NSK_JVMTI_VERIFY(jvmti_env->RedefineClasses(1, &classDef))) { NSK_COMPLAIN1("TEST FAILED: while redefining class %s\n", className); nsk_jvmti_setFailStatus(); - return; } if (!NSK_JVMTI_VERIFY(jvmti_env->Deallocate((unsigned char*)className))) { nsk_jvmti_setFailStatus(); } + if (!NSK_JVMTI_VERIFY(jvmti_env->Deallocate(newClassBytes))) { + nsk_jvmti_setFailStatus(); + } } @@ -136,7 +142,6 @@ void redefineClass(jvmtiEnv *jvmti_env, jclass klass) { static void JNICALL agentProc(jvmtiEnv* jvmti, JNIEnv* agentJNI, void* arg) { - redefineNumber = 1; jni = agentJNI; NSK_DISPLAY0("Waiting for debuggee to become ready\n"); @@ -144,7 +149,7 @@ agentProc(jvmtiEnv* jvmti, JNIEnv* agentJNI, void* arg) { return; testStep = 1; - NSK_DISPLAY0("\n\n>>>> Debugge started, waiting for class loading \n"); + NSK_DISPLAY0(">>>> Debugge started, waiting for class loading \n"); if (!nsk_jvmti_resumeSync()) return; @@ -183,27 +188,20 @@ callbackClassLoad(jvmtiEnv *jvmti_env, JNIEnv* jni_env, jthread thread, jclass klass) { char *className; - char *generic; - if (!NSK_JVMTI_VERIFY(jvmti_env->GetClassSignature(klass, &className, &generic))) { + if (!NSK_JVMTI_VERIFY(jvmti_env->GetClassSignature(klass, &className, NULL))) { nsk_jvmti_setFailStatus(); return; } if (strcmp(className, EXPECTED_CLASS_SIGN) == 0) { - NSK_DISPLAY1("\n\n>>>> Class loaded: %s", className); - NSK_DISPLAY0(", activating breakpoint\n"); + NSK_DISPLAY1(">>>> Class loaded: %s, activating breakpoint\n", className); setBreakPoint(jvmti_env, jni_env, klass); } if (!NSK_JVMTI_VERIFY(jvmti_env->Deallocate((unsigned char*)className))) { nsk_jvmti_setFailStatus(); } - - if (generic != NULL) - if (!NSK_JVMTI_VERIFY(jvmti_env->Deallocate((unsigned char*)generic))) { - nsk_jvmti_setFailStatus(); - } } /* ============================================================================= */ @@ -216,7 +214,7 @@ JNIEXPORT void JNICALL callbackBreakpoint(jvmtiEnv *jvmti_env, JNIEnv* jni_env, jthread thread, jmethodID method, jlocation location) { - NSK_DISPLAY0("\n\n>>>>Breakpoint fired, enabling SINGLE_STEP\n"); + NSK_DISPLAY0(">>>>Breakpoint fired, enabling SINGLE_STEP\n"); enableEvent(jvmti_env, JVMTI_EVENT_SINGLE_STEP, thread); } @@ -266,7 +264,7 @@ callbackSingleStep(jvmtiEnv *jvmti_env, JNIEnv* jni_env, jthread thread, case 2: - NSK_DISPLAY1("\n\n>>>> Checking if redefined method is not obsolete\n", testStep); + NSK_DISPLAY1(">>>> Checking if redefined method is not obsolete\n", testStep); if (!NSK_JVMTI_VERIFY(jvmti->IsMethodObsolete(method, &is_obsolete))) { NSK_COMPLAIN0("TEST FAILED: unable to check method to be obsolete\n"); @@ -283,7 +281,7 @@ callbackSingleStep(jvmtiEnv *jvmti_env, JNIEnv* jni_env, jthread thread, case 3: - NSK_DISPLAY1("\n\n>>>> Popping the currently executing frame\n", testStep); + NSK_DISPLAY1(">>>> Popping the currently executing frame\n", testStep); testStep++; setCurrentStep(jni_env, testStep); @@ -292,7 +290,7 @@ callbackSingleStep(jvmtiEnv *jvmti_env, JNIEnv* jni_env, jthread thread, case 5: if (value < 10) { - NSK_DISPLAY1("\n\n>>>> Disabling single step\n", testStep); + NSK_DISPLAY1(">>>> Disabling single step\n", testStep); disableEvent(jvmti_env, JVMTI_EVENT_SINGLE_STEP, thread); setCurrentStep(jni_env, testStep); } @@ -302,7 +300,7 @@ callbackSingleStep(jvmtiEnv *jvmti_env, JNIEnv* jni_env, jthread thread, } if (!NSK_JVMTI_VERIFY(jvmti_env->Deallocate((unsigned char*) declaringClassName))) { - NSK_COMPLAIN0("TEST FAILED: unable to deallocate memory pointed to method name\n\n"); + NSK_COMPLAIN0("TEST FAILED: unable to deallocate memory pointed to declaringClassName\n\n"); } } @@ -324,24 +322,7 @@ callbackException(jvmtiEnv *jvmti_env, JNIEnv* jni_env, jthread thread, jmethodID method, jlocation location, jobject exception, jmethodID catch_method, jlocation catch_location) { - const char *className; - - className = getClassName(jvmti_env, jni_env, exception); - - if (strcmp(EXPECTED_CLASS_SIGN, className) == 0) { - jclass klass; - - NSK_DISPLAY2("\n\n>>>> Exception %s in thread - %s\n", - className, getThreadName(jni_env, thread)); - - testStep++; - if (!NSK_JNI_VERIFY(jni_env, (klass = jni_env->GetObjectClass(exception)) != NULL)) { - nsk_jvmti_setFailStatus(); - return; - } - - redefineClass(jvmti_env, klass); - } + handleException(false, jvmti_env, jni_env, thread, method, location, exception); } /* ============================================================================= */ @@ -355,15 +336,27 @@ callbackExceptionCatch(jvmtiEnv *jvmti_env, JNIEnv* jni_env, jthread thread, jmethodID method, jlocation location, jobject exception) { - const char *className; + handleException(true, jvmti_env, jni_env, thread, method, location, exception); +} + +/* ============================================================================= */ - className = getClassName(jvmti_env, jni_env, exception); +void handleException(bool isCatch, + jvmtiEnv* jvmti_env, JNIEnv* jni_env, jthread thread, + jmethodID method, jlocation location, + jobject exception) { + const char* className = getClassName(jvmti_env, jni_env, exception); - if (strcmp(EXPECTED_CLASS_SIGN, className) == 0) { + if (className != NULL && strcmp(EXPECTED_CLASS_SIGN, className) == 0) { jclass klass; - NSK_DISPLAY2("\n\n>>>> Caught exception %s in thread - %s\n", - className, getThreadName(jni_env, thread)); + const char* threadName = getThreadName(jvmti_env, jni_env, thread); + NSK_DISPLAY3(">>>> %s %s in thread - %s\n", isCatch ? "Caught exception" : "Exception", + className, threadName != NULL ? threadName : "NULL"); + jvmti->Deallocate((unsigned char*)className); + if (threadName != NULL) { + jvmti->Deallocate((unsigned char*)threadName); + } testStep++; if (!NSK_JNI_VERIFY(jni_env, (klass = jni_env->GetObjectClass(exception)) != NULL)) { @@ -373,11 +366,11 @@ callbackExceptionCatch(jvmtiEnv *jvmti_env, JNIEnv* jni_env, jthread thread, redefineClass(jvmti_env, klass); } + } -/* ============================================================================= */ -int readNewBytecode(jvmtiEnv* jvmti) { +int readNewBytecode(jvmtiEnv* jvmti, jint *newClassSize, unsigned char* *newClassBytes) { char filename[256]; FILE *bytecode; @@ -403,17 +396,19 @@ int readNewBytecode(jvmtiEnv* jvmti) { } fseek(bytecode, 0, SEEK_END); - newClassSize = ftell(bytecode); + *newClassSize = ftell(bytecode); rewind(bytecode); - if (!NSK_JVMTI_VERIFY(jvmti->Allocate(newClassSize, &newClassBytes))) { + if (!NSK_JVMTI_VERIFY(jvmti->Allocate(*newClassSize, newClassBytes))) { NSK_COMPLAIN0("buffer couldn't be allocated\n"); return NSK_FALSE; } - read_bytes = (jint) fread(newClassBytes, 1, newClassSize, bytecode); + read_bytes = (jint) fread(*newClassBytes, 1, *newClassSize, bytecode); fclose(bytecode); - if (read_bytes != newClassSize) { + if (read_bytes != *newClassSize) { NSK_COMPLAIN0("TEST FAILED: error reading file\n"); + jvmti->Deallocate(*newClassBytes); + *newClassBytes = NULL; return NSK_FALSE; } @@ -422,34 +417,41 @@ int readNewBytecode(jvmtiEnv* jvmti) { /* ============================================================================= */ -const char* getThreadName(JNIEnv* jni_env, jthread thread) { +const char* getThreadName(jvmtiEnv* jvmti_env, JNIEnv* jni_env, jthread thread) { jmethodID methodID; jclass klass; jstring jthreadName; + jsize jthreadNameLen; + unsigned char *result = NULL; const char *threadName; - strcpy(chbuffer, ""); - if (!NSK_JNI_VERIFY(jni_env, (klass = jni_env->GetObjectClass(thread)) != NULL)) { nsk_jvmti_setFailStatus(); - return chbuffer; + return NULL; } if (!NSK_JNI_VERIFY(jni_env, (methodID = jni_env->GetMethodID(klass, "getName", "()Ljava/lang/String;")) != NULL)) { nsk_jvmti_setFailStatus(); - return chbuffer; + return NULL; } jthreadName = (jstring) jni_env->CallObjectMethod(thread, methodID); + jthreadNameLen = jni_env->GetStringUTFLength(jthreadName); + + if (!NSK_JVMTI_VERIFY(jvmti_env->Allocate(jthreadNameLen + 1, &result))) { + NSK_COMPLAIN0("buffer couldn't be allocated\n"); + return NULL; + } + threadName = jni_env->GetStringUTFChars(jthreadName, 0); - strcpy(chbuffer, threadName); + memcpy(result, threadName, jthreadNameLen + 1); jni_env->ReleaseStringUTFChars(jthreadName, threadName); - return chbuffer; + return (char*)result; } /* ============================================================================= */ @@ -457,33 +459,19 @@ const char* getThreadName(JNIEnv* jni_env, jthread thread) { const char* getClassName(jvmtiEnv *jvmti_env, JNIEnv* jni_env, jobject object) { char *className; - char *generic; jclass klass; - strcpy(chbuffer, ""); - if (!NSK_JNI_VERIFY(jni_env, (klass = jni_env->GetObjectClass(object)) != NULL)) { nsk_jvmti_setFailStatus(); - return chbuffer; - } - - if (!NSK_JVMTI_VERIFY(jvmti_env->GetClassSignature(klass, &className, &generic))) { - nsk_jvmti_setFailStatus(); - return chbuffer; + return NULL; } - strcpy(chbuffer, className); - - if (!NSK_JVMTI_VERIFY(jvmti_env->Deallocate((unsigned char*)className))) { + if (!NSK_JVMTI_VERIFY(jvmti_env->GetClassSignature(klass, &className, NULL))) { nsk_jvmti_setFailStatus(); + return NULL; } - if (generic != NULL) - if (!NSK_JVMTI_VERIFY(jvmti_env->Deallocate((unsigned char*)generic))) { - nsk_jvmti_setFailStatus(); - } - - return chbuffer; + return className; } /* ============================================================================= */ @@ -546,6 +534,10 @@ Java_nsk_jvmti_scenarios_hotswap_HS201_hs201t002_setThread(JNIEnv *env, if (!NSK_JNI_VERIFY(env, (testedThread = env->NewGlobalRef(thread)) != NULL)) nsk_jvmti_setFailStatus(); + enableEvent(jvmti, JVMTI_EVENT_CLASS_LOAD, testedThread); + enableEvent(jvmti, JVMTI_EVENT_BREAKPOINT, testedThread); + enableEvent(jvmti, JVMTI_EVENT_EXCEPTION, testedThread); + enableEvent(jvmti, JVMTI_EVENT_EXCEPTION_CATCH, testedThread); } /* ============================================================================= */ @@ -665,11 +657,6 @@ jint Agent_Initialize(JavaVM *jvm, char *options, void *reserved) { NSK_DISPLAY0("Enable events\n"); - enableEvent(jvmti, JVMTI_EVENT_CLASS_LOAD, testedThread); - enableEvent(jvmti, JVMTI_EVENT_BREAKPOINT, testedThread); - enableEvent(jvmti, JVMTI_EVENT_EXCEPTION, testedThread); - enableEvent(jvmti, JVMTI_EVENT_EXCEPTION_CATCH, testedThread); - if (!NSK_VERIFY(nsk_jvmti_setAgentProc(agentProc, NULL))) return JNI_ERR; diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/scenarios/hotswap/HS201/hs201t002/newclass/hs201t002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/scenarios/hotswap/HS201/hs201t002/newclass/hs201t002a.java index 3d5a7b946949dc646080a700b4e78dcca53a4128..f5d3d83e9c7aa1580345fbdebd122a083f26fa1f 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/scenarios/hotswap/HS201/hs201t002/newclass/hs201t002a.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/scenarios/hotswap/HS201/hs201t002/newclass/hs201t002a.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, 2018, 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,6 +26,7 @@ package nsk.jvmti.scenarios.hotswap.HS201; public class hs201t002a extends Exception { public hs201t002a () { + System.out.println("Current step: " + hs201t002.currentStep); // Avoid calling classloader to find hs201t002 in doInit() doInit(); } diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/scenarios/hotswap/HS203/hs203t002/hs203t002.java b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/scenarios/hotswap/HS203/hs203t002/hs203t002.java index f872a6dcba3f42ad329d441d988004abe341c944..d9dd4a88c80ff0e543e21c658a8b8df446b74bb3 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/scenarios/hotswap/HS203/hs203t002/hs203t002.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/scenarios/hotswap/HS203/hs203t002/hs203t002.java @@ -79,7 +79,7 @@ public class hs203t002 extends RedefineAgent { Thread.sleep(10000); popThreadFrame(mt); resumeThread(mt); - while(!MyThread.resume2.get());; + while(!MyThread.resume2.get()); Thread.sleep(10000); suspendThread(mt); //mt.suspend(); diff --git a/test/hotspot/jtreg/vmTestbase/nsk/share/Log.java b/test/hotspot/jtreg/vmTestbase/nsk/share/Log.java index 109c3ddd8f7074a8fe6c7173cb8d5146420398db..e171f6daa82e93d873a64157ac2df561e3d84033 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/share/Log.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/share/Log.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 @@ -477,6 +477,13 @@ public class Log extends FinalizableObject { ///////////////////////////////////////////////////////////////// + /** + * Clear all messages from log buffer. + */ + public synchronized void clearLogBuffer() { + logBuffer.clear(); + } + /** * Print all messages from log buffer which were hidden because * of non-verbose mode, diff --git a/test/hotspot/jtreg/vmTestbase/nsk/share/jdb/Launcher.java b/test/hotspot/jtreg/vmTestbase/nsk/share/jdb/Launcher.java index d7aa6c30219aebfa31bd384d0ee300fdc73010a3..a78dabdbe25c5be7a30cc14b3ed83a026a636976 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/share/jdb/Launcher.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/share/jdb/Launcher.java @@ -184,7 +184,7 @@ public class Launcher extends DebugeeBinder { connect.append(argumentHandler.getConnectorName() + ":"); String connectorAddress; - String vmAddress = makeTransportAddress();; + String vmAddress = makeTransportAddress(); if (argumentHandler.isRawLaunchingConnector()) { diff --git a/test/jdk/ProblemList.txt b/test/jdk/ProblemList.txt index 7e19b4bd713a63969830c67912a239a11ef6cfec..25858d1cb7150b1d4ca660b475ecc64ef5313353 100644 --- a/test/jdk/ProblemList.txt +++ b/test/jdk/ProblemList.txt @@ -542,6 +542,7 @@ java/lang/invoke/LFCaching/LFMultiThreadCachingTest.java 8151492 generic- java/lang/invoke/LFCaching/LFGarbageCollectedTest.java 8078602 generic-all java/lang/invoke/lambda/LambdaFileEncodingSerialization.java 8249079 linux-x64 java/lang/invoke/RicochetTest.java 8251969 generic-all +java/lang/Enum/ConstantDirectoryOptimalCapacity.java 8282120 generic-all ############################################################################ @@ -824,8 +825,8 @@ jdk/jfr/event/compiler/TestCodeSweeper.java 8225209 generic- jdk/jfr/event/os/TestThreadContextSwitches.java 8247776 windows-all jdk/jfr/startupargs/TestStartName.java 8214685 windows-x64 jdk/jfr/startupargs/TestStartDuration.java 8214685 windows-x64 -jdk/jfr/event/oldobject/TestLargeRootSet.java 8276333 generic-x64 jdk/jfr/api/consumer/recordingstream/TestOnEvent.java 8255404 linux-x64 +jdk/jfr/jvm/TestWaste.java 8282427 generic-all ############################################################################ diff --git a/test/jdk/com/sun/crypto/provider/KeyAgreement/DHKeyAgreementPadding.java b/test/jdk/com/sun/crypto/provider/KeyAgreement/DHKeyAgreementPadding.java new file mode 100644 index 0000000000000000000000000000000000000000..dc963bf62677bca077a4d518790f83a4a2f05da6 --- /dev/null +++ b/test/jdk/com/sun/crypto/provider/KeyAgreement/DHKeyAgreementPadding.java @@ -0,0 +1,74 @@ +/* + * 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 8281628 + * @library /test/lib + * @summary ensure padding bytes are always added when generated secret + * is smaller than buffer size. + */ + +import javax.crypto.KeyAgreement; +import java.security.KeyPair; +import java.security.KeyPairGenerator; +import java.util.Arrays; +import java.util.HexFormat; + +public class DHKeyAgreementPadding { + + public static void main(String[] args) throws Exception { + + byte[] aliceSecret = new byte[80]; + byte[] bobSecret = new byte[80]; + + KeyAgreement alice = KeyAgreement.getInstance("DiffieHellman"); + KeyAgreement bob = KeyAgreement.getInstance("DiffieHellman"); + + // The probability of an error is 0.2% or 1/500. Try more times. + for (int i = 0; i < 5000; i++) { + KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("DiffieHellman"); + keyPairGen.initialize(512); + KeyPair aliceKeyPair = keyPairGen.generateKeyPair(); + KeyPair bobKeyPair = keyPairGen.generateKeyPair(); + + // Different stale data + Arrays.fill(aliceSecret, (byte)'a'); + Arrays.fill(bobSecret, (byte)'b'); + + alice.init(aliceKeyPair.getPrivate()); + alice.doPhase(bobKeyPair.getPublic(), true); + int aliceLen = alice.generateSecret(aliceSecret, 0); + + bob.init(bobKeyPair.getPrivate()); + bob.doPhase(aliceKeyPair.getPublic(), true); + int bobLen = bob.generateSecret(bobSecret, 0); + + if (!Arrays.equals(aliceSecret, 0, aliceLen, bobSecret, 0, bobLen)) { + System.out.println(HexFormat.ofDelimiter(":").formatHex(aliceSecret, 0, aliceLen)); + System.out.println(HexFormat.ofDelimiter(":").formatHex(bobSecret, 0, bobLen)); + throw new RuntimeException("Different secrets observed at runs #" + i); + } + } + } +} diff --git a/test/jdk/com/sun/jdi/ConstantPoolInfo.java b/test/jdk/com/sun/jdi/ConstantPoolInfo.java index 097ab535cf241ad8f52d4d78e1c4bb535cff0ff5..5d5c2a6a5d9b6ebce7635ee781612d4ae594e68d 100644 --- a/test/jdk/com/sun/jdi/ConstantPoolInfo.java +++ b/test/jdk/com/sun/jdi/ConstantPoolInfo.java @@ -241,7 +241,7 @@ public class ConstantPoolInfo extends TestScaffold { if (magic != JAVA_MAGIC) { failure("fatal bad class file format"); } - expectedMinorVersion = in.readShort();; + expectedMinorVersion = in.readShort(); expectedMajorVersion = in.readShort(); expectedCpoolCount = in.readUnsignedShort(); in.close(); diff --git a/test/jdk/com/sun/jdi/GenericsTest.java b/test/jdk/com/sun/jdi/GenericsTest.java index 28a3d69a8d693f8e46df16e36a9ef7bb8e6dc966..f12a5f74322ae4ab0feb5030ae8681e4c0a0c0a6 100644 --- a/test/jdk/com/sun/jdi/GenericsTest.java +++ b/test/jdk/com/sun/jdi/GenericsTest.java @@ -40,7 +40,7 @@ import java.util.*; /********** target program **********/ class GenericsTarg { - static Gen1 genField = new Gen1();; + static Gen1 genField = new Gen1(); static Sub1 sub1Field = new Sub1(); String[] strArray = null; diff --git a/test/jdk/com/sun/jdi/JdbOptions.java b/test/jdk/com/sun/jdi/JdbOptions.java index a4e3bfd356fbadd2bd8ab25b0194a847a34dafb5..4a6c8550fc6e842943f5536d93204af0c064c019 100644 --- a/test/jdk/com/sun/jdi/JdbOptions.java +++ b/test/jdk/com/sun/jdi/JdbOptions.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 @@ -151,6 +151,22 @@ public class JdbOptions { .expectedArg("-XX:StartFlightRecording:dumponexit=true,maxsize=500M") .expectedArg("-XX:FlightRecorderOptions:repository=jfrrep"); + // -R is tested to see if options are passed through. + test("-R-Dprop1=val1", + "-R-Dprop2=val 2", + "-R-Xmixed", + "-R--add-modules", "-Rjdk.attach", + "-R-Xcheck:jni", + "-R--enable-preview", + "-connect", + "com.sun.jdi.CommandLineLaunch:vmexec=java,main=" + targ + " " + outFilename + " prop1 prop2") + .expectedProp("prop1", "val1") + .expectedProp("prop2", "val 2") + .expectedArg("-Xmixed") + .expectedArg("--add-modules=jdk.attach") + .expectedArg("-Xcheck:jni") + .expectedArg("--enable-preview"); + } private static class TestResult { diff --git a/test/jdk/java/awt/Component/CompEventOnHiddenComponent/CompEventOnHiddenComponent.java b/test/jdk/java/awt/Component/CompEventOnHiddenComponent/CompEventOnHiddenComponent.java index c643aae1f002d7d61fb5234d8e533bfae3d68947..0c1734cb1ccd120e9a0bdbb1c1a83f12276c7cdb 100644 --- a/test/jdk/java/awt/Component/CompEventOnHiddenComponent/CompEventOnHiddenComponent.java +++ b/test/jdk/java/awt/Component/CompEventOnHiddenComponent/CompEventOnHiddenComponent.java @@ -86,7 +86,7 @@ public class CompEventOnHiddenComponent EventQueue.invokeLater(new Runnable() { public void run() { JFrame parentWindow = new JFrame("JFrame 1"); - JButton component = new JButton("JButton 1");; + JButton component = new JButton("JButton 1"); JButton smallButton = new JButton("Small Button"); diff --git a/test/jdk/java/awt/EmbeddedFrame/EmbeddedFrameGrabTest/EmbeddedFrameGrabTest.java b/test/jdk/java/awt/EmbeddedFrame/EmbeddedFrameGrabTest/EmbeddedFrameGrabTest.java index e186e7ac1320a2e9f3d1f4081159d725bcc6fd9c..535e6c68aa545f30eac55905c7a5d0d984c92efe 100644 --- a/test/jdk/java/awt/EmbeddedFrame/EmbeddedFrameGrabTest/EmbeddedFrameGrabTest.java +++ b/test/jdk/java/awt/EmbeddedFrame/EmbeddedFrameGrabTest/EmbeddedFrameGrabTest.java @@ -81,7 +81,7 @@ public class EmbeddedFrameGrabTest { = clazz.getConstructor(new Class[]{long.class}); final Frame embedded_frame = (Frame) constructor.newInstance(new Object[]{ - new Long(hwnd)});; + new Long(hwnd)}); final JComboBox combo = new JComboBox<>(new String[]{ "Item 1", "Item 2" }); diff --git a/test/jdk/java/awt/Frame/SetMinimumSizeTest/SetMinimumSizeTest1.java b/test/jdk/java/awt/Frame/SetMinimumSizeTest/SetMinimumSizeTest1.java new file mode 100644 index 0000000000000000000000000000000000000000..f6560d7e66f5b2f90f6b2f55f3539c57bf200262 --- /dev/null +++ b/test/jdk/java/awt/Frame/SetMinimumSizeTest/SetMinimumSizeTest1.java @@ -0,0 +1,88 @@ +/* + * 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 headful + * @summary Verify that increase in Frame's minimumSize gets reflected in the subsequent getSize call + * @run main SetMinimumSizeTest1 + */ + +import java.awt.Button; +import java.awt.Dimension; +import java.awt.EventQueue; +import java.awt.Frame; +import java.awt.Robot; + +public class SetMinimumSizeTest1 { + + private static Frame frame; + private static volatile Dimension dimension; + private static volatile Dimension actualDimension; + + public static void createGUI() { + frame = new Frame(); + frame.add(new Button("Button")); + frame.setSize(140, 140); + frame.setLocationRelativeTo(null); + frame.setVisible(true); + } + + public static void doTest() throws Exception { + try { + EventQueue.invokeAndWait(() -> createGUI()); + + Robot robot = new Robot(); + robot.setAutoDelay(100); + robot.waitForIdle(); + + EventQueue.invokeAndWait(() -> { + dimension = frame.getSize(); + dimension.width += 20; + dimension.height += 20; + frame.setMinimumSize(dimension); + frame.invalidate(); + frame.validate(); + }); + + robot.waitForIdle(); + + EventQueue.invokeAndWait(() -> { + actualDimension = frame.getSize(); + }); + + if (!actualDimension.equals(dimension)) { + throw new RuntimeException("Test Failed\n" + + "expected dimension:(" + dimension.width + "," + dimension.height +")\n" + + "actual dimension:(" + actualDimension.width + "," + actualDimension.height + ")"); + } + } finally { + EventQueue.invokeAndWait(() -> frame.dispose()); + } + } + + public static void main(String[] args) throws Exception { + doTest(); + } +} + diff --git a/test/jdk/java/awt/Frame/SetMinimumSizeTest/SetMinimumSizeTest2.java b/test/jdk/java/awt/Frame/SetMinimumSizeTest/SetMinimumSizeTest2.java new file mode 100644 index 0000000000000000000000000000000000000000..ca0763e19fad453732349d4762055df46a31f397 --- /dev/null +++ b/test/jdk/java/awt/Frame/SetMinimumSizeTest/SetMinimumSizeTest2.java @@ -0,0 +1,97 @@ +/* + * 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 headful + * @summary Verify frame resizes back to minimumSize on calling pack + * @run main SetMinimumSizeTest2 + */ + +import java.awt.Button; +import java.awt.Dimension; +import java.awt.EventQueue; +import java.awt.Frame; +import java.awt.Robot; + +public class SetMinimumSizeTest2 { + + private static Frame frame; + private static volatile Dimension dimension; + private static volatile Dimension actualDimension; + + public static void createGUI() { + frame = new Frame(); + frame.add(new Button("Button")); + frame.setMinimumSize(new Dimension(140, 140)); + frame.setLocationRelativeTo(null); + frame.setVisible(true); + } + + public static void doTest() throws Exception { + try { + EventQueue.invokeAndWait(() -> createGUI()); + + Robot robot = new Robot(); + robot.setAutoDelay(100); + robot.waitForIdle(); + + EventQueue.invokeAndWait(() -> { + dimension = frame.getSize(); + }); + + EventQueue.invokeAndWait(() -> { + frame.setSize(dimension.width + 20, dimension.height + 20); + frame.invalidate(); + frame.validate(); + }); + + robot.waitForIdle(); + + EventQueue.invokeAndWait(() -> { + frame.pack(); + frame.invalidate(); + frame.validate(); + }); + + robot.waitForIdle(); + + EventQueue.invokeAndWait(() -> { + actualDimension = frame.getSize(); + }); + + if (!actualDimension.equals(dimension)) { + throw new RuntimeException("Test Failed\n" + + "expected dimension:(" + dimension.width + "," + dimension.height +")\n" + + "actual dimension:(" + actualDimension.width + "," + actualDimension.height + ")"); + } + } finally { + EventQueue.invokeAndWait(() -> frame.dispose()); + } + } + + public static void main(String[] args) throws Exception { + doTest(); + } +} + diff --git a/test/jdk/java/awt/PrintJob/PrintArcTest/PrintArcTest.java b/test/jdk/java/awt/PrintJob/PrintArcTest/PrintArcTest.java index 15cf121607ce81e3f169a4aba19efcb6b32c8e7d..7e9023b1afcf09e67df27c7360ae03e5ec784f9c 100644 --- a/test/jdk/java/awt/PrintJob/PrintArcTest/PrintArcTest.java +++ b/test/jdk/java/awt/PrintJob/PrintArcTest/PrintArcTest.java @@ -65,7 +65,7 @@ public class PrintArcTest extends Panel implements ActionListener { } private Frame getFrame() { - Container cont = getParent();; + Container cont = getParent(); while ( !(cont instanceof Frame ) ) { cont = cont.getParent(); diff --git a/test/jdk/java/awt/Robot/HiDPIScreenCapture/HiDPIRobotScreenCaptureTest.java b/test/jdk/java/awt/Robot/HiDPIScreenCapture/HiDPIRobotScreenCaptureTest.java index 85378f00ad6765d238fb3ffd742bbdf4cd6b02ec..db34b1714b533000f8a0077d65be09643657b92c 100644 --- a/test/jdk/java/awt/Robot/HiDPIScreenCapture/HiDPIRobotScreenCaptureTest.java +++ b/test/jdk/java/awt/Robot/HiDPIScreenCapture/HiDPIRobotScreenCaptureTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2017, 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 @@ -27,20 +27,26 @@ import java.awt.Color; import java.awt.Frame; import java.awt.Graphics; import java.awt.Panel; +import java.awt.Point; import java.awt.Rectangle; import java.awt.Robot; import java.awt.image.BufferedImage; import javax.swing.UIManager; +import javax.imageio.ImageIO; +import java.io.File; +import java.io.IOException; /** * @test * @key headful - * @bug 8073320 - * @summary Windows HiDPI support + * @bug 8073320 8280861 + * @summary Linux and Windows HiDPI support * @author Alexander Scherbatiy * @requires (os.family == "linux" | os.family == "windows") * @run main/othervm -Dsun.java2d.win.uiScaleX=3 -Dsun.java2d.win.uiScaleY=2 * HiDPIRobotScreenCaptureTest + * @run main/othervm -Dsun.java2d.uiScale=1 HiDPIRobotScreenCaptureTest + * @run main/othervm -Dsun.java2d.uiScale=2 HiDPIRobotScreenCaptureTest */ public class HiDPIRobotScreenCaptureTest { @@ -60,7 +66,14 @@ public class HiDPIRobotScreenCaptureTest { } Frame frame = new Frame(); - frame.setBounds(40, 30, 400, 300); + // Position the frame on prime number coordinates (mind OFFSET) + // to avoid them being multiple of the desktop scale; this tests Linux + // color picker better. + // Also, the position should be far enough from the top left + // corner of the screen to reduce the chance of being repositioned + // by the system because that area's occupied by the global + // menu bar and such. + frame.setBounds(78, 92, 100, 100); frame.setUndecorated(true); Panel panel = new Panel(new BorderLayout()); @@ -86,11 +99,12 @@ public class HiDPIRobotScreenCaptureTest { frame.setVisible(true); Robot robot = new Robot(); robot.waitForIdle(); - Thread.sleep(200); + robot.delay(500); Rectangle rect = canvas.getBounds(); rect.setLocation(canvas.getLocationOnScreen()); + System.out.println("Creating screen capture of " + rect); BufferedImage image = robot.createScreenCapture(rect); frame.dispose(); @@ -101,20 +115,38 @@ public class HiDPIRobotScreenCaptureTest { throw new RuntimeException("Wrong image size!"); } - if (image.getRGB(w / 4, h / 4) != COLORS[0].getRGB()) { - throw new RuntimeException("Wrong image color!"); - } - - if (image.getRGB(3 * w / 4, h / 4) != COLORS[1].getRGB()) { - throw new RuntimeException("Wrong image color!"); - } + checkRectColor(image, new Rectangle(0, 0, w / 2, h / 2), COLORS[0]); + checkRectColor(image, new Rectangle(w / 2, 0, w / 2, h / 2), COLORS[1]); + checkRectColor(image, new Rectangle(0, h / 2, w / 2, h / 2), COLORS[2]); + checkRectColor(image, new Rectangle(w / 2, h / 2, w / 2, h / 2), COLORS[3]); + } - if (image.getRGB(w / 4, 3 * h / 4) != COLORS[2].getRGB()) { - throw new RuntimeException("Wrong image color!"); - } + private static final int OFFSET = 5; + static void checkRectColor(BufferedImage image, Rectangle rect, Color expectedColor) { + System.out.println("Checking rectangle " + rect + " to have color " + expectedColor); + final Point[] pointsToCheck = new Point[] { + new Point(rect.x + OFFSET, rect.y + OFFSET), // top left corner + new Point(rect.x + rect.width - OFFSET, rect.y + OFFSET), // top right corner + new Point(rect.x + rect.width / 2, rect.y + rect.height / 2), // center + new Point(rect.x + OFFSET, rect.y + rect.height - OFFSET), // bottom left corner + new Point(rect.x + rect.width - OFFSET, rect.y + rect.height - OFFSET) // bottom right corner + }; - if (image.getRGB(3 * w / 4, 3 * h / 4) != COLORS[3].getRGB()) { - throw new RuntimeException("Wrong image color!"); + for (final var point : pointsToCheck) { + System.out.print("Checking color at " + point + " to be equal to " + expectedColor); + final int actualColor = image.getRGB(point.x, point.y); + if (actualColor != expectedColor.getRGB()) { + System.out.println("... Mismatch: found " + new Color(actualColor) + " instead. Check image.png."); + try { + ImageIO.write(image, "png", new File("image.png")); + } catch(IOException e) { + System.out.println("failed to save image.png."); + e.printStackTrace(); + } + throw new RuntimeException("Wrong image color!"); + } else { + System.out.println("... OK"); + } } } -} \ No newline at end of file +} diff --git a/test/jdk/java/awt/Robot/HiDPIScreenCapture/ScreenCaptureGtkTest.java b/test/jdk/java/awt/Robot/HiDPIScreenCapture/ScreenCaptureGtkTest.java new file mode 100644 index 0000000000000000000000000000000000000000..6ba5ec18e0a90519496fa9ac2377c9afda0b3c4d --- /dev/null +++ b/test/jdk/java/awt/Robot/HiDPIScreenCapture/ScreenCaptureGtkTest.java @@ -0,0 +1,142 @@ +/* + * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, JetBrains s.r.o.. All rights reserved. + * 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.awt.Canvas; +import java.awt.Color; +import java.awt.Frame; +import java.awt.Graphics; +import java.awt.Panel; +import java.awt.Point; +import java.awt.Rectangle; +import java.awt.Robot; +import java.awt.image.BufferedImage; +import javax.swing.UIManager; +import javax.imageio.ImageIO; +import java.io.File; +import java.io.IOException; + + +/** + * @test + * @key headful + * @bug 8280861 + * @summary Verifies Robot screen capture capabilities with different + * Gtk backends and presence of UI scaling + * @requires os.family == "linux" + * @run main/othervm -Djdk.gtk.version=2 -Dsun.java2d.uiScale=1 ScreenCaptureGtkTest + * @run main/othervm -Djdk.gtk.version=3 -Dsun.java2d.uiScale=1 ScreenCaptureGtkTest + */ + +public class ScreenCaptureGtkTest { + private static final Color[] COLORS = { + Color.GREEN, Color.BLUE, Color.ORANGE, Color.RED}; + + public static void main(String[] args) throws Exception { + final int topOffset = 50; + final int leftOffset = 50; + + Frame frame = new Frame(); + // Position the frame such that color picker will work with + // prime number coordinates (mind the offset) to avoid them being + // multiple of the desktop scale; this tests Linux color picker better. + // Also, the position should be far enough from the top left + // corner of the screen to reduce the chance of being repositioned + // by the system because that area's occupied by the global + // menu bar and such. + frame.setBounds(89, 99, 100, 100); + frame.setUndecorated(true); + + Panel panel = new Panel(new BorderLayout()); + Canvas canvas = new Canvas() { + @Override + public void paint(Graphics g) { + super.paint(g); + int w = getWidth(); + int h = getHeight(); + g.setColor(COLORS[0]); + g.fillRect(0, 0, w, h); + // Paint several distinct pixels next to one another + // in order to test color picker's precision. + for (int i = 1; i < COLORS.length; i++) { + g.setColor(COLORS[i]); + g.fillRect(leftOffset + i, topOffset, 1, 1); + } + } + }; + + panel.add(canvas); + frame.add(panel); + frame.setVisible(true); + Robot robot = new Robot(); + robot.waitForIdle(); + robot.delay(500); + + captureImageOf(frame, robot); + + final Point screenLocation = frame.getLocationOnScreen(); + try { + checkPixelColors(robot, screenLocation.x + leftOffset, + screenLocation.y + topOffset); + } finally { + robot.delay(100); + frame.dispose(); + } + } + + static void checkPixelColors(Robot robot, int x, int y) { + for (int i = 0; i < COLORS.length; i++) { + final Color actualColor = robot.getPixelColor(x + i, y); + System.out.print("Checking color at " + (x + i) + ", " + y + " to be equal to " + COLORS[i]); + if (!actualColor.equals(COLORS[i])) { + System.out.println("... Mismatch: found " + actualColor + " instead"); + saveImage(); + throw new RuntimeException("Wrong screen pixel color"); + + } else { + System.out.println("... OK"); + } + } + } + + private static BufferedImage image; + + static void captureImageOf(Frame frame, Robot robot) { + Rectangle rect = frame.getBounds(); + rect.setLocation(frame.getLocationOnScreen()); + + System.out.println("Creating screen capture of " + rect); + image = robot.createScreenCapture(rect); + } + + static void saveImage() { + System.out.println("Check image.png"); + try { + ImageIO.write(image, "png", new File("image.png")); + } catch(IOException e) { + System.out.println("failed to save image.png."); + e.printStackTrace(); + } + } +} diff --git a/test/jdk/java/awt/SplashScreen/GenerateTestImage.java b/test/jdk/java/awt/SplashScreen/GenerateTestImage.java index 93def3347568f7b6ce7042417ca25eaf3d959434..ddde69ca295da3acd5c560a1d32bab7d42ce30a7 100644 --- a/test/jdk/java/awt/SplashScreen/GenerateTestImage.java +++ b/test/jdk/java/awt/SplashScreen/GenerateTestImage.java @@ -43,7 +43,7 @@ public class GenerateTestImage { Graphics2D graphics2D = image.createGraphics(); graphics2D.setColor(Color.red); graphics2D.fillOval(0, 0, IMAGE_SIZE, IMAGE_SIZE); - graphics2D.dispose();; + graphics2D.dispose(); ImageIO.write(image, "png", file); } diff --git a/test/jdk/java/awt/color/ICC_ColorSpace/SetTagDataValidation.java b/test/jdk/java/awt/color/ICC_ColorSpace/SetTagDataValidation.java new file mode 100644 index 0000000000000000000000000000000000000000..92faced75ba0d0a9da86ad589e968345a433eedd --- /dev/null +++ b/test/jdk/java/awt/color/ICC_ColorSpace/SetTagDataValidation.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 + * @bug 8282577 + * @summary Verify setting data for a tag doesn't invalidate the profile. + */ + +import java.awt.color.ColorSpace; +import java.awt.color.ICC_ColorSpace; +import java.awt.color.ICC_Profile; + +public final class SetTagDataValidation { + + public static void main(String[] args) throws Exception { + + ICC_Profile srgb = ICC_Profile.getInstance(ColorSpace.CS_sRGB); + // Create a new profile, using the srgb data but private to us. + ICC_Profile icc = ICC_Profile.getInstance(srgb.getData()); + + // Get data for some tag, which one isn't important so long as it exists + int tag = ICC_Profile.icSigBlueColorantTag; + byte[] tagData = icc.getData(tag); + if (tagData == null) { + throw new RuntimeException("No data for tag"); + } + // Set the data to be the SAME data which ought to be a harmless no-op + icc.setData(tag, tagData); + + // Perform a color conversion - from rgb to rgb but it doesn't matter + // we just need to verify the op is applied and results are sane. + + ColorSpace cs = new ICC_ColorSpace(icc); + float[] in = new float[3]; + in[0] = 0.4f; + in[1] = 0.5f; + in[2] = 0.6f; + + // the toRGB op previously threw an exception - or crashed + float[] out = cs.toRGB(in); + // If we get this far let's validate the results. + if (out == null || out.length !=3) { + throw new RuntimeException("out array invalid"); + } + for (int i=0;i 0.01)) { + throw new RuntimeException("Inaccurate no-op conversion"); + } + } + } +} diff --git a/test/jdk/java/awt/color/ICC_Profile/MTGetData.java b/test/jdk/java/awt/color/ICC_Profile/MTGetData.java index 5b2572e14f1c82ed29a1289c95569ec239e6b745..7d634cb0f4a507e56cc5936d778fd5f86cbc428a 100644 --- a/test/jdk/java/awt/color/ICC_Profile/MTGetData.java +++ b/test/jdk/java/awt/color/ICC_Profile/MTGetData.java @@ -23,6 +23,7 @@ import java.awt.color.ColorSpace; import java.awt.color.ICC_Profile; +import java.awt.color.CMMException; import java.lang.reflect.Field; import java.lang.reflect.Modifier; import java.util.ArrayList; @@ -103,6 +104,7 @@ public final class MTGetData { icc.setData(tag, data2); } } catch (IllegalArgumentException ignored) { + System.err.println("Ignoring " + ignored); } catch (Throwable throwable) { throwable.printStackTrace(); failed = true; diff --git a/test/jdk/java/awt/font/GlyphVector/MultiSlotFontTest.java b/test/jdk/java/awt/font/GlyphVector/MultiSlotFontTest.java new file mode 100644 index 0000000000000000000000000000000000000000..65acd420345b8839b6d38847039ca92faa7e357a --- /dev/null +++ b/test/jdk/java/awt/font/GlyphVector/MultiSlotFontTest.java @@ -0,0 +1,136 @@ +/* + * 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 8240756 + * @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" + * @run main MultiSlotFontTest + */ + +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Font; +import java.awt.Graphics; +import java.awt.Image; +import java.awt.RenderingHints; +import java.awt.font.FontRenderContext; +import java.awt.font.GlyphVector; +import java.awt.image.BufferedImage; +import sun.font.StandardGlyphVector; +import sun.java2d.OSXOffScreenSurfaceData; +import sun.java2d.SunGraphics2D; +import sun.java2d.SurfaceData; +import sun.java2d.loops.SurfaceType; + +public class MultiSlotFontTest { + + private static final int WIDTH = 100; + private static final int HEIGHT = 60; + + private static final String TEST_STR = "\u3042\u3044\u3046\u3048\u304Aabc"; + private static final int EXPECTED_HEIGHT = 10; + private static final int EXPECTED_WIDTH = 77; + private static final int LIMIT_DIFF_HEIGHT = 3; + private static final int LIMIT_DIFF_WIDTH = 15; + + public static void main(String[] args) throws Exception { + MultiSlotFontTest test = new MultiSlotFontTest(); + } + + public MultiSlotFontTest() { + BufferedImage img = createImage(); + + SurfaceData sd = OSXOffScreenSurfaceData.createDataIC(img, + SurfaceType.IntRgb); + SunGraphics2D g2d = new SunGraphics2D(sd, + Color.BLACK, Color.WHITE, null); + Font font = g2d.getFont(); + + if (font.canDisplayUpTo(TEST_STR) != -1) { + System.out.println("There is no capable font. Skipping the test."); + System.out.println("Font: " + font); + return; + } + + FontRenderContext frc = new FontRenderContext(null, false, false); + StandardGlyphVector gv = new StandardGlyphVector(font, TEST_STR, frc); + g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, + RenderingHints.VALUE_ANTIALIAS_OFF); + g2d.drawGlyphVector(gv, 0.0f, (float)(HEIGHT - 5)); + g2d.dispose(); + + Dimension d = getBounds(img); + + if (Math.abs(d.height - EXPECTED_HEIGHT) > LIMIT_DIFF_HEIGHT || + Math.abs(d.width - EXPECTED_WIDTH) > LIMIT_DIFF_WIDTH) { + debugOut(img); + throw new RuntimeException( + "Incorrect GlyphVector shape " + d + "," + gv); + } + } + + private static BufferedImage createImage() { + BufferedImage image = new BufferedImage(WIDTH, HEIGHT, + BufferedImage.TYPE_INT_RGB); + Graphics g = image.createGraphics(); + g.setColor(Color.WHITE); + g.fillRect(0, 0, WIDTH, HEIGHT); + g.dispose(); + return image; + } + + private Dimension getBounds(BufferedImage img) { + int top = HEIGHT; + int left = WIDTH; + int right = 0; + int bottom = 0; + for (int y = 0; y < HEIGHT; y++) { + for (int x = 0; x < WIDTH; x++) { + if ((img.getRGB(x, y) & 0xFFFFFF) == 0) { + if (top > y) top = y; + if (bottom < y) bottom = y; + if (left > x) left = x; + if (right < x) right = x; + } + } + } + return new Dimension(right - left, bottom - top); + } + + private void debugOut(BufferedImage img) { + for (int y = 0; y < HEIGHT; y++) { + for (int x = 0; x < WIDTH; x++) { + int c = img.getRGB(x, y) & 0xFFFFFF; + if (c == 0) { + System.out.print("*"); + } else { + System.out.print(" "); + } + } + System.out.println(); + } + } +} diff --git a/test/jdk/java/awt/image/DrawImage/ByteIndexedDitherTest.java b/test/jdk/java/awt/image/DrawImage/ByteIndexedDitherTest.java new file mode 100644 index 0000000000000000000000000000000000000000..0c0aa49eb4356eeaadcd5bd8e1812aeb5f8720d4 --- /dev/null +++ b/test/jdk/java/awt/image/DrawImage/ByteIndexedDitherTest.java @@ -0,0 +1,83 @@ +/* + * 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 8280964 + * @summary Tests that drawing to a ByteIndexed image dithers correctly. + */ + +import java.awt.Color; +import java.awt.Graphics2D; +import java.awt.image.BufferedImage; + +public class ByteIndexedDitherTest { + + public static void main(String[] args) { + BufferedImage bgr = createBGRImage(); + BufferedImage indexed = createIndexedImage(bgr); + checkImage(indexed); + } + + static BufferedImage createBGRImage() { + + int sz = 8; + BufferedImage img; + img = new BufferedImage(sz, sz, BufferedImage.TYPE_3BYTE_BGR); + Graphics2D g = img.createGraphics(); + Color c = new Color(0, 0, 254); + g.setColor(c); + g.fillRect(0, 0, sz, sz); + g.dispose(); + + return img; + } + + static BufferedImage createIndexedImage(BufferedImage srcImage) { + + int w = srcImage.getWidth(null); + int h = srcImage.getHeight(null); + BufferedImage + indexedImg = new BufferedImage(w, h, BufferedImage.TYPE_BYTE_INDEXED); + Graphics2D g = indexedImg.createGraphics(); + g.drawImage(srcImage, 0, 0, w, h, null); + g.dispose(); + return indexedImg; + } + + static void checkImage(BufferedImage image) { + int wid = image.getWidth(); + int hgt = image.getHeight(); + for (int y=0; y NO_PROXY = List.of(Proxy.NO_PROXY); @@ -75,11 +79,13 @@ public class ProxyTest implements HttpCallback { ProxySelector.setDefault(new MyProxySelector()); try { InetAddress loopback = InetAddress.getLoopbackAddress(); - server = new TestHttpServer(new ProxyTest(), 1, 10, loopback, 0); + server = HttpServer.create(new InetSocketAddress(loopback, 0), 10, "/", new ProxyTestHandler()); + server.setExecutor(Executors.newSingleThreadExecutor()); + server.start(); URL url = URIBuilder.newBuilder() .scheme("http") .loopback() - .port(server.getLocalPort()) + .port(server.getAddress().getPort()) .toURL(); System.out.println("client opening connection to: " + url); HttpURLConnection urlc = (HttpURLConnection)url.openConnection(); @@ -93,8 +99,23 @@ public class ProxyTest implements HttpCallback { throw new RuntimeException(e); } finally { if (server != null) { - server.terminate(); + server.stop(1); } } } } + +class ProxyTestHandler implements HttpHandler { + + @Override + public void handle(HttpExchange exchange) throws IOException { + try { + exchange.sendResponseHeaders(200, 0); + } catch (IOException e) { + e.printStackTrace(); + } + try(PrintWriter pw = new PrintWriter(exchange.getResponseBody(), false, Charset.forName("UTF-8"))) { + pw.print("Hello ."); + } + } +} diff --git a/test/jdk/java/net/SocketException/TestSocketExceptionCtor.java b/test/jdk/java/net/SocketException/TestSocketExceptionCtor.java new file mode 100644 index 0000000000000000000000000000000000000000..18611924bec151e4edd40f7ff76c35d75e2eed27 --- /dev/null +++ b/test/jdk/java/net/SocketException/TestSocketExceptionCtor.java @@ -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. + * + * 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 8282686 + * @summary Verify cause and message handling of SocketException + */ +import java.net.SocketException; +import java.util.Objects; + +public class TestSocketExceptionCtor { + public static void main(String... args) { + String message = "message"; + Throwable cause = new RuntimeException(); + + testException(new SocketException(cause), cause.toString(), cause); + testException(new SocketException(message, cause), message, cause); + } + + private static void testException(SocketException se, + String expectedMessage, + Throwable expectedCause) { + var message = se.getMessage(); + if (!Objects.equals(message, expectedMessage)) { + throw new RuntimeException("Unexpected message " + message); + } + + var cause = se.getCause(); + if (cause != expectedCause) { + throw new RuntimeException("Unexpected cause"); + } + } +} diff --git a/test/jdk/java/net/URL/PerConnectionProxy.java b/test/jdk/java/net/URL/PerConnectionProxy.java index 6ce25b9a50eae019fbd01ab45bb1dc86b8955cf9..1877e7cef2877844250a10b285377a98133ef8a4 100644 --- a/test/jdk/java/net/URL/PerConnectionProxy.java +++ b/test/jdk/java/net/URL/PerConnectionProxy.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 @@ -24,42 +24,47 @@ /* @test * @bug 4920526 * @summary Needs per connection proxy support for URLs - * @modules java.base/sun.net.www - * @library ../../../sun/net/www/httptest/ /test/lib - * @build ClosedChannelList TestHttpServer HttpTransaction HttpCallback + * @library /test/lib * @compile PerConnectionProxy.java * @run main/othervm -Dhttp.proxyHost=inexistant -Dhttp.proxyPort=8080 PerConnectionProxy */ -import java.net.*; -import java.io.*; - +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.PrintWriter; +import java.net.HttpURLConnection; +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.net.Proxy; +import java.net.ServerSocket; +import java.net.Socket; +import java.net.URL; +import java.nio.charset.Charset; +import java.util.concurrent.Executors; + +import com.sun.net.httpserver.HttpExchange; +import com.sun.net.httpserver.HttpHandler; +import com.sun.net.httpserver.HttpServer; import jdk.test.lib.net.URIBuilder; -public class PerConnectionProxy implements HttpCallback { - static TestHttpServer server; - - public void request (HttpTransaction req) { - req.setResponseEntityBody ("Hello ."); - try { - req.sendResponse (200, "Ok"); - req.orderlyClose(); - } catch (IOException e) { - } - } +public class PerConnectionProxy { + static HttpServer server; public static void main(String[] args) { try { InetAddress loopbackAddress = InetAddress.getLoopbackAddress(); - server = new TestHttpServer(new PerConnectionProxy(), 1, 10, loopbackAddress, 0); - ProxyServer pserver = new ProxyServer(loopbackAddress, server.getLocalPort()); + server = HttpServer.create(new InetSocketAddress(loopbackAddress, 0), 10, "/", new PerConnectionProxyHandler()); + server.setExecutor(Executors.newSingleThreadExecutor()); + server.start(); + ProxyServer pserver = new ProxyServer(loopbackAddress, server.getAddress().getPort()); // start proxy server new Thread(pserver).start(); URL url = URIBuilder.newBuilder() .scheme("http") .loopback() - .port(server.getLocalPort()) + .port(server.getAddress().getPort()) .toURLUnchecked(); // for non existing proxy expect an IOException @@ -73,7 +78,6 @@ public class PerConnectionProxy implements HttpCallback { } catch (IOException ioex) { // expected } - // for NO_PROXY, expect direct connection try { HttpURLConnection urlc = (HttpURLConnection)url.openConnection (Proxy.NO_PROXY); @@ -82,7 +86,6 @@ public class PerConnectionProxy implements HttpCallback { } catch (IOException ioex) { throw new RuntimeException("direct connection should succeed :"+ioex.getMessage()); } - // for a normal proxy setting expect to see connection // goes through that proxy try { @@ -101,10 +104,9 @@ public class PerConnectionProxy implements HttpCallback { throw new RuntimeException(e); } finally { if (server != null) { - server.terminate(); + server.stop(1); } } - } static class ProxyServer extends Thread { @@ -145,7 +147,6 @@ public class PerConnectionProxy implements HttpCallback { private void processRequests() throws Exception { // connection set to the tunneling mode - Socket serverSocket = new Socket(serverInetAddr, serverPort); ProxyTunnel clientToServer = new ProxyTunnel( clientSocket, serverSocket); @@ -161,7 +162,6 @@ public class PerConnectionProxy implements HttpCallback { clientToServer.close(); serverToClient.close(); - } /** @@ -221,6 +221,20 @@ public class PerConnectionProxy implements HttpCallback { } catch (IOException ignored) { } } } + } +} +class PerConnectionProxyHandler implements HttpHandler { + + @Override + public void handle(HttpExchange exchange) throws IOException { + try { + exchange.sendResponseHeaders(200, 0); + } catch (IOException e) { + } + try(PrintWriter pw = new PrintWriter(exchange.getResponseBody(), false, Charset.forName("UTF-8"))) { + pw.print("Hello ."); + } } } + diff --git a/test/jdk/java/net/URLConnection/B5052093.java b/test/jdk/java/net/URLConnection/B5052093.java index f5434f9528b96ad2f8e6d83dd2cdba109f0588d9..c93098f2de89e1252fe5cbd68a42e143f14011de 100644 --- a/test/jdk/java/net/URLConnection/B5052093.java +++ b/test/jdk/java/net/URLConnection/B5052093.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2019, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -23,21 +23,31 @@ /* * @test + * @modules java.base/sun.net.www.protocol.file * @bug 5052093 - * @modules java.base/sun.net.www java.base/sun.net.www.protocol.file - * @library ../../../sun/net/www/httptest/ - * @build HttpCallback TestHttpServer ClosedChannelList HttpTransaction - * @run main B5052093 + * @library /test/lib + * @run main/othervm B5052093 * @summary URLConnection doesn't support large files */ -import java.net.*; -import java.io.*; -import sun.net.www.protocol.file.FileURLConnection; + +import java.io.File; +import java.io.IOException; +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.net.URL; +import java.net.URLConnection; +import java.util.concurrent.Executors; + +import com.sun.net.httpserver.HttpExchange; +import com.sun.net.httpserver.HttpHandler; +import com.sun.net.httpserver.HttpServer; import static java.net.Proxy.NO_PROXY; +import jdk.test.lib.net.URIBuilder; +import sun.net.www.protocol.file.FileURLConnection; -public class B5052093 implements HttpCallback { - private static TestHttpServer server; - private static long testSize = ((long) (Integer.MAX_VALUE)) + 2; +public class B5052093 { + private static HttpServer server; + static long testSize = ((long) (Integer.MAX_VALUE)) + 2; public static class LargeFile extends File { public LargeFile() { @@ -55,20 +65,18 @@ public class B5052093 implements HttpCallback { } } - public void request(HttpTransaction req) { - try { - req.setResponseHeader("content-length", Long.toString(testSize)); - req.sendResponse(200, "OK"); - } catch (IOException e) { - e.printStackTrace(); - } - } - public static void main(String[] args) throws Exception { InetAddress loopback = InetAddress.getLoopbackAddress(); - server = new TestHttpServer(new B5052093(), 1, 10, loopback, 0); + server = HttpServer.create(new InetSocketAddress(loopback, 0), 10, "/", new B5052093Handler()); + server.setExecutor(Executors.newSingleThreadExecutor()); + server.start(); try { - URL url = new URL("http://" + server.getAuthority() + "/foo"); + URL url = URIBuilder.newBuilder() + .scheme("http") + .loopback() + .port(server.getAddress().getPort()) + .path("/foo") + .build().toURL(); URLConnection conn = url.openConnection(NO_PROXY); int i = conn.getContentLength(); long l = conn.getContentLengthLong(); @@ -89,7 +97,20 @@ public class B5052093 implements HttpCallback { throw new RuntimeException("Wrong content-length from file"); } } finally { - server.terminate(); + server.stop(1); + } + } +} + +class B5052093Handler implements HttpHandler { + @Override + public void handle(HttpExchange exchange) throws IOException { + try { + exchange.getResponseHeaders().set("content-length", Long.toString(B5052093.testSize)); + exchange.sendResponseHeaders(200, 0); + exchange.close(); + } catch (IOException e) { + e.printStackTrace(); } } } diff --git a/test/jdk/java/net/httpclient/AggregateRequestBodyTest.java b/test/jdk/java/net/httpclient/AggregateRequestBodyTest.java index 05d27547a15f2bd54956106ca17b2a43b0c1b1e9..60a35a42a0687d4c469fdcc19c1cd914c7f816d7 100644 --- a/test/jdk/java/net/httpclient/AggregateRequestBodyTest.java +++ b/test/jdk/java/net/httpclient/AggregateRequestBodyTest.java @@ -485,7 +485,7 @@ public class AggregateRequestBodyTest implements HttpServerAdapters { subscriber.subscriptionCF.thenAccept(s -> s.request(1)); List result = subscriber.resultCF.join(); assertEquals(result, List.of()); - assertTrue(subscriber.items.isEmpty());; + assertTrue(subscriber.items.isEmpty()); } // verifies that error emitted by upstream publishers are propagated downstream. diff --git a/test/jdk/java/net/httpclient/CancelRequestTest.java b/test/jdk/java/net/httpclient/CancelRequestTest.java index de48316a25b01030b32749c8058c7730d4e3f006..95d56fdbcce2e0918a38c39b231c5cf2f0d826b1 100644 --- a/test/jdk/java/net/httpclient/CancelRequestTest.java +++ b/test/jdk/java/net/httpclient/CancelRequestTest.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 @@ -23,7 +23,7 @@ /* * @test - * @bug 8245462 8229822 + * @bug 8245462 8229822 8254786 * @summary Tests cancelling the request. * @library /test/lib http2/server * @key randomness diff --git a/test/jdk/java/nio/channels/AsynchronousFileChannel/Basic.java b/test/jdk/java/nio/channels/AsynchronousFileChannel/Basic.java index 55de744c0dbed3e93c25d62fa29d45b8869dab90..0beffac0ed515a5c41185fb96ac11a45bcccef44 100644 --- a/test/jdk/java/nio/channels/AsynchronousFileChannel/Basic.java +++ b/test/jdk/java/nio/channels/AsynchronousFileChannel/Basic.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2010, 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 @@ -22,18 +22,37 @@ */ /* @test - * @bug 4607272 6822643 6830721 6842687 + * @bug 4607272 5041655 6822643 6830721 6842687 * @summary Unit test for AsynchronousFileChannel * @key randomness */ -import java.nio.file.*; -import java.nio.channels.*; -import java.nio.ByteBuffer; import java.io.File; import java.io.IOException; -import java.util.*; -import java.util.concurrent.*; +import java.nio.ByteBuffer; +import java.nio.channels.AsynchronousCloseException; +import java.nio.channels.AsynchronousFileChannel; +import java.nio.channels.ClosedChannelException; +import java.nio.channels.CompletionHandler; +import java.nio.channels.FileLock; +import java.nio.channels.NonWritableChannelException; +import java.nio.channels.OverlappingFileLockException; +import java.nio.file.Path; +import java.nio.file.StandardOpenOption; +import java.util.ArrayList; +import java.util.EnumSet; +import java.util.List; +import java.util.Random; +import java.util.Set; +import java.util.concurrent.CancellationException; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.Executors; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Future; +import java.util.concurrent.ThreadFactory; +import java.util.concurrent.TimeoutException;; +import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicReference; import static java.nio.file.StandardOpenOption.*; @@ -176,7 +195,12 @@ public class Basic { // test 1 - acquire lock and check that tryLock throws // OverlappingFileLockException try { - fl = ch.lock().get(); + long pos = rand.nextInt(Integer.MAX_VALUE); + fl = ch.lock(pos, 0, false).get(); + long expectedSize = Long.MAX_VALUE - pos; + if(fl.size() != expectedSize) + throw new RuntimeException("Lock size " + fl.size() + + " != " + expectedSize + " for position " + pos); } catch (ExecutionException x) { throw new RuntimeException(x); } catch (InterruptedException x) { @@ -192,7 +216,12 @@ public class Basic { fl.release(); // test 2 - acquire try and check that lock throws OverlappingFileLockException - fl = ch.tryLock(); + long pos = rand.nextInt(Integer.MAX_VALUE); + fl = ch.tryLock(pos, 0, false); + long expectedSize = Long.MAX_VALUE - pos; + if(fl.size() != expectedSize) + throw new RuntimeException("Lock size " + fl.size() + " != " + + expectedSize + " for position " + pos); if (fl == null) throw new RuntimeException("Unable to acquire lock"); try { diff --git a/test/jdk/java/nio/channels/FileChannel/Lock.java b/test/jdk/java/nio/channels/FileChannel/Lock.java index 8dee478ea822be1561d64322795590f0b5117be7..7a055a6d107748439fd8c5835fa1203158ceb676 100644 --- a/test/jdk/java/nio/channels/FileChannel/Lock.java +++ b/test/jdk/java/nio/channels/FileChannel/Lock.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2016, 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 @@ -22,12 +22,19 @@ */ /* @test - * @bug 4429043 4493595 6332756 6709457 7146506 + * @bug 4429043 4493595 5041655 6332756 6709457 7146506 * @summary Test FileChannel file locking */ -import java.io.*; -import java.nio.channels.*; +import java.io.BufferedReader; +import java.io.File; +import java.io.FileOutputStream; +import java.io.InputStreamReader; +import java.io.RandomAccessFile; +import java.nio.channels.FileChannel; +import java.nio.channels.FileLock; +import java.nio.channels.OverlappingFileLockException; +import java.util.Random; import static java.nio.file.StandardOpenOption.*; /** @@ -126,12 +133,23 @@ public class Lock { static void test2(File blah, boolean b) throws Exception { try (RandomAccessFile raf = new RandomAccessFile(blah, "rw")) { FileChannel channel = raf.getChannel(); - FileLock lock; - if (b) - lock = channel.lock(); - else - lock = channel.tryLock(); - lock.release(); + try (FileLock lock = b ? channel.lock() : channel.tryLock()) { + } + + Random rnd = new Random(System.currentTimeMillis()); + long position = rnd.nextInt(Integer.MAX_VALUE); + long expectedSize = Long.MAX_VALUE - position; + + for (boolean shared : new boolean[] {false, true}) { + try (FileLock lock = b ? channel.lock(position, 0, false) : + channel.tryLock(position, 0, false)) { + if(lock.size() != expectedSize) + throw new RuntimeException("Lock size " + lock.size() + + " != " + expectedSize + + " for position " + position + " of " + + (shared ? "exclusive" : "shared") + " lock"); + } + } } } diff --git a/test/jdk/java/nio/channels/FileLock/Overlaps.java b/test/jdk/java/nio/channels/FileLock/Overlaps.java new file mode 100644 index 0000000000000000000000000000000000000000..64293e2996db6a6be22594f360634d28cbd7f55c --- /dev/null +++ b/test/jdk/java/nio/channels/FileLock/Overlaps.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 5041655 + * @summary Verify FileLock.overlaps + * @run testng Overlaps + */ +import java.io.IOException; +import java.nio.ByteBuffer; +import java.nio.channels.FileChannel; +import java.nio.channels.FileLock; +import java.nio.file.Files; +import java.nio.file.Path; + +import static java.lang.Boolean.*; +import static java.nio.file.StandardOpenOption.*; + +import static org.testng.Assert.assertEquals; +import org.testng.annotations.AfterClass; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; + +public class Overlaps { + private static final long POS = 27; + private static final long SIZE = 42; + + private static FileChannel fc; + + @BeforeClass + public void before() throws IOException { + Path path = Files.createTempFile(Path.of("."), "foo", ".bar"); + fc = FileChannel.open(path, CREATE, WRITE, DELETE_ON_CLOSE); + fc.position(POS); + fc.write(ByteBuffer.wrap(new byte[(int)SIZE])); + } + + @AfterClass + public void after() throws IOException { + fc.close(); + } + + @DataProvider + public Object[][] ranges() { + return new Object[][] { + {POS, SIZE, -1,-1, FALSE}, + {POS, SIZE, 0, -1, FALSE}, + {POS, SIZE, POS - 1, -1, FALSE}, + {POS, SIZE, POS + SIZE/2, -1, FALSE}, + {POS, SIZE, POS + SIZE, -1, FALSE}, + {POS, SIZE, -1, POS, FALSE}, + {POS, SIZE, -1, POS + SIZE/2, TRUE}, + {POS, SIZE, POS - 2, 1, FALSE}, + {POS, SIZE, POS + 1, 1, TRUE}, + {POS, SIZE, POS + SIZE/2, 0, TRUE}, + {POS, SIZE, Long.MAX_VALUE, 2, FALSE}, + {POS, SIZE, POS + SIZE / 2, Long.MAX_VALUE, TRUE}, + {POS, SIZE, 0, 0, TRUE}, + {Long.MAX_VALUE - SIZE/2, 0, 0, SIZE, FALSE}, + {Long.MAX_VALUE - SIZE/2, 0, Long.MAX_VALUE - SIZE/4, SIZE, TRUE}, + {Long.MAX_VALUE - SIZE/2, 0, Long.MAX_VALUE - SIZE, 0, TRUE}, + {Long.MAX_VALUE - SIZE, 0, Long.MAX_VALUE - SIZE/2, 0, TRUE} + }; + } + + @Test(dataProvider = "ranges") + public void overlaps(long lockPos, long lockSize, long pos, long size, + boolean overlaps) throws IOException { + try (FileLock lock = fc.lock(lockPos, lockSize, false)) { + assertEquals(lock.overlaps(pos, size), overlaps); + } + } +} diff --git a/test/jdk/java/nio/channels/SocketChannel/CloseTimeoutChannel.java b/test/jdk/java/nio/channels/SocketChannel/CloseTimeoutChannel.java index 10fdcaaaea6bd6c6b7b4bfe1f0d4b3d4c4a280f0..c715cad8c7c3f20ccda3e591a9eb524b0b51263e 100644 --- a/test/jdk/java/nio/channels/SocketChannel/CloseTimeoutChannel.java +++ b/test/jdk/java/nio/channels/SocketChannel/CloseTimeoutChannel.java @@ -102,7 +102,7 @@ public class CloseTimeoutChannel { System.out.println(INDENT+"Listening on port "+ _listener.socket().getLocalPort()); ByteBuffer buf=ByteBuffer.allocate(5); - Socket client=_listener.accept().socket();; + Socket client=_listener.accept().socket(); System.out.println(INDENT+"Accepted client"); OutputStream out=client.getOutputStream(); diff --git a/test/jdk/java/nio/charset/CharsetDecoder/ASCIIDecode.java b/test/jdk/java/nio/charset/CharsetDecoder/ASCIIDecode.java new file mode 100644 index 0000000000000000000000000000000000000000..330c2c49a0705da9a36a71162c46bebf0f8e5c4c --- /dev/null +++ b/test/jdk/java/nio/charset/CharsetDecoder/ASCIIDecode.java @@ -0,0 +1,55 @@ +/* + * 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 8283325 + * @summary Ensure that decoding to ASCII from a stream with a non-ASCII + * character correctly decodes up until the byte in error. + */ + +import java.nio.*; +import java.nio.charset.*; +import java.util.Arrays; + +public class ASCIIDecode { + + public static void main(String[] args) throws Exception { + final Charset ascii = Charset.forName("US-ASCII"); + final CharsetDecoder decoder = ascii.newDecoder(); + + byte[] ba = new byte[] { 0x60, 0x60, 0x60, (byte)0xFF }; + + // Repeat enough times to test that interpreter and JIT:ed versions + // behave the same (without the patch for 8283325 this fails within + // 50 000 iterations on the system used for verification) + for (int i = 0; i < 100_000; i++) { + ByteBuffer bb = ByteBuffer.wrap(ba); + char[] ca = new char[4]; + CharBuffer cb = CharBuffer.wrap(ca); + CoderResult buf = decoder.decode(bb, cb, true); + if (ca[0] != 0x60 || ca[1] != 0x60 || ca[2] != 0x60) { + throw new RuntimeException("Unexpected output on iteration " + i); + } + } + } +} diff --git a/test/jdk/java/nio/file/Files/CopyAndMove.java b/test/jdk/java/nio/file/Files/CopyAndMove.java index 981fb332fc0c4cd109dc7f3c479e2caab61682bc..e91f3e3713b742fb109409df56536e6ab9bc8740 100644 --- a/test/jdk/java/nio/file/Files/CopyAndMove.java +++ b/test/jdk/java/nio/file/Files/CopyAndMove.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2018, 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 @@ -22,7 +22,7 @@ */ /* @test - * @bug 4313887 6838333 6917021 7006126 6950237 8006645 8201407 + * @bug 4313887 6838333 6917021 7006126 6950237 8006645 8201407 8267820 * @summary Unit test for java.nio.file.Files copy and move methods (use -Dseed=X to set PRNG seed) * @library .. /test/lib * @build jdk.test.lib.Platform jdk.test.lib.RandomFactory @@ -672,16 +672,15 @@ public class CopyAndMove { checkBasicAttributes(basicAttributes, readAttributes(source, BasicFileAttributes.class, linkOptions)); + // check POSIX attributes are copied + if (!Platform.isWindows() && testPosixAttributes) { + checkPosixAttributes( + readAttributes(source, PosixFileAttributes.class, linkOptions), + readAttributes(target, PosixFileAttributes.class, linkOptions)); + } + // verify other attributes when same provider if (source.getFileSystem().provider() == target.getFileSystem().provider()) { - - // check POSIX attributes are copied - if (!Platform.isWindows() && testPosixAttributes) { - checkPosixAttributes( - readAttributes(source, PosixFileAttributes.class, linkOptions), - readAttributes(target, PosixFileAttributes.class, linkOptions)); - } - // check DOS attributes are copied if (Platform.isWindows()) { checkDosAttributes( diff --git a/test/jdk/java/nio/file/Files/probeContentType/Basic.java b/test/jdk/java/nio/file/Files/probeContentType/Basic.java index b404673b2f4ff081f3963d1314a2bfbfb06067b6..74e4cd5ab39e5eb51310cebd12ff8cc1af7ace92 100644 --- a/test/jdk/java/nio/file/Files/probeContentType/Basic.java +++ b/test/jdk/java/nio/file/Files/probeContentType/Basic.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2021, 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 @@ -161,7 +161,7 @@ public class Basic { new ExType("doc", List.of("application/msword")), new ExType("docx", List.of("application/vnd.openxmlformats-officedocument.wordprocessingml.document")), new ExType("gz", List.of("application/gzip", "application/x-gzip")), - new ExType("jar", List.of("application/java-archive", "application/x-java-archive")), + new ExType("jar", List.of("application/java-archive", "application/x-java-archive", "application/jar")), new ExType("jpg", List.of("image/jpeg")), new ExType("js", List.of("text/javascript", "application/javascript")), new ExType("json", List.of("application/json")), diff --git a/test/jdk/java/rmi/dgc/dgcImplInsulation/DGCImplInsulation.java b/test/jdk/java/rmi/dgc/dgcImplInsulation/DGCImplInsulation.java index c4a15b28bb1cb3e3f40445898bcfc80afcc221e1..9a0490beb0ff3bde0c8e97656a5a39d46fde6051 100644 --- a/test/jdk/java/rmi/dgc/dgcImplInsulation/DGCImplInsulation.java +++ b/test/jdk/java/rmi/dgc/dgcImplInsulation/DGCImplInsulation.java @@ -68,7 +68,7 @@ public class DGCImplInsulation implements java.rmi.Remote { new ProtectionDomain( new CodeSource(null, (Certificate[]) null), perms) }); - Remote impl = new DGCImplInsulation();; + Remote impl = new DGCImplInsulation(); try { Remote stub = (Remote) java.security.AccessController.doPrivileged( diff --git a/test/jdk/java/security/misc/Versions.java b/test/jdk/java/security/misc/Versions.java index 6c14b2bc212ddbb096378ddbca77e5fc90314a45..ebfe9a13a88faf27295af114805cfca1cb026dd4 100644 --- a/test/jdk/java/security/misc/Versions.java +++ b/test/jdk/java/security/misc/Versions.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 @@ -51,7 +51,7 @@ public class Versions { "src/java.xml.crypto/share/legal/santuario.md", Pattern.compile("## Apache Santuario v(?\\S+)"), "java.xml.crypto/santuario.md"}, - {"make/data/publicsuffixlist/VERSION", + {"src/java.base/share/data/publicsuffixlist/VERSION", Pattern.compile("list/(?[0-9a-f]+)/public_suffix_list.dat"), "src/java.base/share/legal/public_suffix.md", Pattern.compile("list/(?[0-9a-f]+)/public_suffix_list.dat"), diff --git a/test/jdk/java/text/Format/DecimalFormat/ToLocalizedPatternTest.java b/test/jdk/java/text/Format/DecimalFormat/ToLocalizedPatternTest.java new file mode 100644 index 0000000000000000000000000000000000000000..6d8ab9c9a0cd4953d97c5473e6e66f4390f424bb --- /dev/null +++ b/test/jdk/java/text/Format/DecimalFormat/ToLocalizedPatternTest.java @@ -0,0 +1,61 @@ +/* + * 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 8282929 + * @summary Verifies that toLocalizedPattern() method correctly returns + * monetary symbols in a currency formatter + * @run testng ToLocalizedPatternTest + */ + +import static org.testng.Assert.assertEquals; +import org.testng.annotations.Test; + +import java.text.DecimalFormat; +import java.text.DecimalFormatSymbols; +import java.util.Locale; + +@Test +public class ToLocalizedPatternTest { + private static final char MONETARY_GROUPING = 'g'; + private static final char MONETARY_DECIMAL = 'd'; + + public void testToLocalizedPattern() { + var dfs = new DecimalFormatSymbols(Locale.US); + + // Customize the decimal format symbols + dfs.setMonetaryGroupingSeparator(MONETARY_GROUPING); + dfs.setMonetaryDecimalSeparator(MONETARY_DECIMAL); + + // create a currency formatter + var cf = (DecimalFormat)DecimalFormat.getCurrencyInstance(Locale.US); + cf.setDecimalFormatSymbols(dfs); + + // check + assertEquals(cf.toLocalizedPattern(), + cf.toPattern() + .replace(',', MONETARY_GROUPING) + .replace('.', MONETARY_DECIMAL)); + } +} diff --git a/test/jdk/java/text/Format/NumberFormat/IntlTestDecimalFormatSymbols.java b/test/jdk/java/text/Format/NumberFormat/IntlTestDecimalFormatSymbols.java index cd19fee1e35110f74ef9655c573c3a56fdae8384..30905ee46f16c1359995d610e3d37615dce35131 100644 --- a/test/jdk/java/text/Format/NumberFormat/IntlTestDecimalFormatSymbols.java +++ b/test/jdk/java/text/Format/NumberFormat/IntlTestDecimalFormatSymbols.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2016, 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 @@ -23,6 +23,7 @@ /* * @test + * @bug 8282625 * @library /java/text/testlib * @summary test International Decimal Format Symbols */ @@ -60,6 +61,14 @@ public class IntlTestDecimalFormatSymbols extends IntlTest // just do some VERY basic tests to make sure that get/set work + if (!fr.getLocale().equals(Locale.FRENCH)) { + errln("ERROR: French DecimalFormatSymbols not Locale.FRENCH"); + } + + if (!en.getLocale().equals(Locale.ENGLISH)) { + errln("ERROR: English DecimalFormatSymbols not Locale.ENGLISH"); + } + char zero = en.getZeroDigit(); fr.setZeroDigit(zero); if(fr.getZeroDigit() != en.getZeroDigit()) { diff --git a/test/jdk/java/time/tck/java/time/zone/TCKZoneRules.java b/test/jdk/java/time/tck/java/time/zone/TCKZoneRules.java index 3f6c17b277a4bf5fc9a08b82e0deb7fe131bbac7..d44216b69b56e92de8a93a5f35113f846c058d3b 100644 --- a/test/jdk/java/time/tck/java/time/zone/TCKZoneRules.java +++ b/test/jdk/java/time/tck/java/time/zone/TCKZoneRules.java @@ -1072,7 +1072,7 @@ public class TCKZoneRules { ); OffsetDateTime before_time_of_stdOffsetTransition1 = OffsetDateTime.of(time_of_stdOffsetTransition1, stdOffset1).minusSeconds(1); - OffsetDateTime after_time_of_stdOffsetTransition1 = OffsetDateTime.of(time_of_stdOffsetTransition1, stdOffset1).plusSeconds(1);; + OffsetDateTime after_time_of_stdOffsetTransition1 = OffsetDateTime.of(time_of_stdOffsetTransition1, stdOffset1).plusSeconds(1); assertEquals(zoneRule.getStandardOffset(before_time_of_stdOffsetTransition1.toInstant()), stdOffset1); assertEquals(zoneRule.getStandardOffset(after_time_of_stdOffsetTransition1.toInstant()), stdOffset2); diff --git a/test/jdk/java/time/test/java/time/format/TestDateTimeFormatterBuilder.java b/test/jdk/java/time/test/java/time/format/TestDateTimeFormatterBuilder.java index 6dd54ad6880dbffc11bc67a41eb177dc39a9b758..567b331b004a483f89de71a61a65b670ca356510 100644 --- a/test/jdk/java/time/test/java/time/format/TestDateTimeFormatterBuilder.java +++ b/test/jdk/java/time/test/java/time/format/TestDateTimeFormatterBuilder.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 @@ -1051,7 +1051,7 @@ public class TestDateTimeFormatterBuilder { {"d", "Value(DayOfMonth)"}, {"dd", "Value(DayOfMonth,2)"}, - {"F", "Value(AlignedDayOfWeekInMonth)"}, + {"F", "Value(AlignedWeekOfMonth)"}, {"Q", "Value(QuarterOfYear)"}, {"QQ", "Value(QuarterOfYear,2)"}, diff --git a/test/jdk/java/util/Currency/CurrencyTest.java b/test/jdk/java/util/Currency/CurrencyTest.java index ad7c596485bbd815eb4592db03ec6140ec65ad80..f82b032e2f818adee64f1f3db3e9ac83486b5c89 100644 --- a/test/jdk/java/util/Currency/CurrencyTest.java +++ b/test/jdk/java/util/Currency/CurrencyTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2021, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -139,7 +139,7 @@ public class CurrencyTest { /* * check currency changes - * In current implementation, there is no data of old currency and transition date at jdk/make/data/currency/CurrencyData.properties. + * In current implementation, there is no data of old currency and transition date at jdk/src/java.base/share/data/currency/CurrencyData.properties. * So, all the switch data arrays are empty. In the future, if data of old currency and transition date are necessary for any country, the * arrays here can be updated so that the program can check the currency switch. */ diff --git a/test/jdk/java/util/Currency/ValidateISO4217.java b/test/jdk/java/util/Currency/ValidateISO4217.java index 40bb55cfd1f9ff61f4130ed3bba89593123f393e..a0f09842ffe2cc3ca120fca5dc48406467e8c6c7 100644 --- a/test/jdk/java/util/Currency/ValidateISO4217.java +++ b/test/jdk/java/util/Currency/ValidateISO4217.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2021, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -24,7 +24,7 @@ * @test * @bug 4691089 4819436 4942982 5104960 6544471 6627549 7066203 7195759 * 8039317 8074350 8074351 8145952 8187946 8193552 8202026 8204269 - * 8208746 8209775 8264792 8274658 + * 8208746 8209775 8264792 8274658 8283277 * @summary Validate ISO 4217 data for Currency class. * @modules java.base/java.util:open * jdk.localedata @@ -101,7 +101,7 @@ public class ValidateISO4217 { static final String otherCodes = "ADP-AFA-ATS-AYM-AZM-BEF-BGL-BOV-BYB-BYR-CHE-CHW-CLF-COU-CUC-CYP-" + "DEM-EEK-ESP-FIM-FRF-GHC-GRD-GWP-IEP-ITL-LTL-LUF-LVL-MGF-MRO-MTL-MXV-MZM-NLG-" - + "PTE-ROL-RUR-SDD-SIT-SKK-SRG-STD-TMM-TPE-TRL-VEF-UYI-USN-USS-VEB-VED-" + + "PTE-ROL-RUR-SDD-SIT-SLL-SKK-SRG-STD-TMM-TPE-TRL-VEF-UYI-USN-USS-VEB-VED-" + "XAG-XAU-XBA-XBB-XBC-XBD-XDR-XFO-XFU-XPD-XPT-XSU-XTS-XUA-XXX-" + "YUM-ZMK-ZWD-ZWN-ZWR"; diff --git a/test/jdk/java/util/Currency/tablea1.txt b/test/jdk/java/util/Currency/tablea1.txt index 7716863419fc454d186443de5aedc8e63e6ce6a7..62d71c8c94b6d2ba5ebe7cdbc7c843bbee30bd53 100644 --- a/test/jdk/java/util/Currency/tablea1.txt +++ b/test/jdk/java/util/Currency/tablea1.txt @@ -1,12 +1,12 @@ # # -# Amendments up until ISO 4217 AMENDMENT NUMBER 170 -# (As of 1 Oct 2021) +# Amendments up until ISO 4217 AMENDMENT NUMBER 171 +# (As of 16 Mar 2022) # # Version FILEVERSION=3 -DATAVERSION=170 +DATAVERSION=171 # ISO 4217 currency data AF AFN 971 2 @@ -218,7 +218,7 @@ RS RSD 941 2 CS CSD 891 2 #CS EUR 978 2 SC SCR 690 2 -SL SLL 694 2 +SL SLE 925 2 SG SGD 702 2 SK EUR 978 2 # MA 131 diff --git a/test/jdk/java/util/HashMap/WhiteBoxResizeTest.java b/test/jdk/java/util/HashMap/WhiteBoxResizeTest.java index e7374dff5cd2dacd23da144607f72b1665aa5112..ad02b3000e218c8f0f4b02e6bca2efc6610f32a4 100644 --- a/test/jdk/java/util/HashMap/WhiteBoxResizeTest.java +++ b/test/jdk/java/util/HashMap/WhiteBoxResizeTest.java @@ -1,5 +1,6 @@ /* * Copyright (c) 2018, 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 @@ -21,113 +22,299 @@ * questions. */ +import org.testng.annotations.DataProvider; import org.testng.annotations.Test; import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; import java.lang.invoke.MethodType; import java.lang.invoke.VarHandle; +import java.util.AbstractMap; +import java.util.AbstractSet; +import java.util.ArrayList; +import java.util.Arrays; import java.util.HashMap; +import java.util.Iterator; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; -import java.util.concurrent.ThreadLocalRandom; +import java.util.Set; +import java.util.WeakHashMap; +import java.util.function.Consumer; import java.util.function.Supplier; -import java.util.stream.IntStream; -import static java.util.stream.Collectors.toMap; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertNull; /* * @test - * @bug 8210280 + * @bug 8210280 8281631 * @modules java.base/java.util:open - * @summary White box tests for HashMap internals around table resize + * @summary White box tests for HashMap-related internals around table sizing * @run testng WhiteBoxResizeTest - * @key randomness */ public class WhiteBoxResizeTest { - final ThreadLocalRandom rnd = ThreadLocalRandom.current(); + final MethodHandle TABLE_SIZE_FOR; - final VarHandle THRESHOLD; - final VarHandle TABLE; + final VarHandle HM_TABLE; + final VarHandle WHM_TABLE; public WhiteBoxResizeTest() throws ReflectiveOperationException { - Class mClass = HashMap.class; - String nodeClassName = mClass.getName() + "$Node"; - Class nodeArrayClass = Class.forName("[L" + nodeClassName + ";"); - MethodHandles.Lookup lookup = MethodHandles.privateLookupIn(mClass, MethodHandles.lookup()); - TABLE = lookup.findVarHandle(mClass, "table", nodeArrayClass); - this.TABLE_SIZE_FOR = lookup.findStatic( - mClass, "tableSizeFor", - MethodType.methodType(int.class, int.class)); - this.THRESHOLD = lookup.findVarHandle(mClass, "threshold", int.class); + MethodHandles.Lookup hmlookup = MethodHandles.privateLookupIn(HashMap.class, MethodHandles.lookup()); + TABLE_SIZE_FOR = hmlookup.findStatic( + HashMap.class, "tableSizeFor", MethodType.methodType(int.class, int.class)); + HM_TABLE = hmlookup.unreflectVarHandle(HashMap.class.getDeclaredField("table")); + + MethodHandles.Lookup whmlookup = MethodHandles.privateLookupIn(WeakHashMap.class, MethodHandles.lookup()); + WHM_TABLE = whmlookup.unreflectVarHandle(WeakHashMap.class.getDeclaredField("table")); } + /* + * utility methods + */ + int tableSizeFor(int n) { try { return (int) TABLE_SIZE_FOR.invoke(n); - } catch (Throwable t) { throw new AssertionError(t); } + } catch (Throwable t) { + throw new AssertionError(t); + } } - Object[] table(HashMap map) { + Object[] table(Map map) { try { - return (Object[]) TABLE.get(map); - } catch (Throwable t) { throw new AssertionError(t); } + VarHandle vh = map instanceof WeakHashMap ? WHM_TABLE : HM_TABLE; + return (Object[]) vh.get(map); + } catch (Throwable t) { + throw new AssertionError(t); + } } - int capacity(HashMap map) { + int capacity(Map map) { return table(map).length; } - @Test - public void testTableSizeFor() { - assertEquals(tableSizeFor(0), 1); - assertEquals(tableSizeFor(1), 1); - assertEquals(tableSizeFor(2), 2); - assertEquals(tableSizeFor(3), 4); - assertEquals(tableSizeFor(15), 16); - assertEquals(tableSizeFor(16), 16); - assertEquals(tableSizeFor(17), 32); - int maxSize = 1 << 30; - assertEquals(tableSizeFor(maxSize - 1), maxSize); - assertEquals(tableSizeFor(maxSize), maxSize); - assertEquals(tableSizeFor(maxSize + 1), maxSize); - assertEquals(tableSizeFor(Integer.MAX_VALUE), maxSize); + // creates a map with size mappings + Map makeMap(int size) { + Map map = new HashMap<>(); + putN(map, size); + return map; + } + + // creates a "fake" map: size() returns the given size, but + // the entrySet iterator returns only one entry + Map fakeMap(int size) { + return new AbstractMap<>() { + public Set> entrySet() { + return new AbstractSet>() { + public int size() { + return size; + } + + public Iterator> iterator() { + return Set.of(Map.entry("1", "1")).iterator(); + } + }; + } + }; + } + + void putN(Map map, int n) { + for (int i = 0; i < n; i++) { + String string = Integer.toString(i); + map.put(string, string); + } + } + + /* + * tests of tableSizeFor + */ + + @DataProvider(name = "tableSizeFor") + public Object[][] tableSizeForCases() { + final int MAX = 1 << 30; + return new Object[][] { + // tableSizeFor(arg), expected + { 0, 1 }, + { 1, 1 }, + { 2, 2 }, + { 3, 4 }, + { 4, 4 }, + { 5, 8 }, + { 15, 16 }, + { 16, 16 }, + { 17, 32 }, + { MAX-1, MAX }, + { MAX, MAX }, + { MAX+1, MAX }, + { Integer.MAX_VALUE, MAX } + }; + } + + @Test(dataProvider = "tableSizeFor") + public void tableSizeFor(int arg, int expected) { + assertEquals(tableSizeFor(arg), expected); } - @Test - public void capacityTestDefaultConstructor() { - capacityTestDefaultConstructor(new HashMap<>()); - capacityTestDefaultConstructor(new LinkedHashMap<>()); + /* + * tests for lazy table allocation + */ + + @DataProvider(name = "lazy") + public Object[][] lazyTableAllocationCases() { + return new Object[][]{ + {new HashMap<>()}, + // { new WeakHashMap<>() }, // WHM doesn't allocate lazily + {new LinkedHashMap<>()} + }; } - void capacityTestDefaultConstructor(HashMap map) { + @Test(dataProvider = "lazy") + public void lazyTableAllocation(Map map) { assertNull(table(map)); + } - map.put(1, 1); - assertEquals(capacity(map), 16); // default initial capacity + /* + * tests for default capacity (no-arg constructor) + */ - map.putAll(IntStream.range(0, 64).boxed().collect(toMap(i -> i, i -> i))); - assertEquals(capacity(map), 128); + @DataProvider(name = "defaultCapacity") + public Object[][] defaultCapacityCases() { + return new Supplier[][]{ + {() -> new HashMap<>()}, + {() -> new LinkedHashMap<>()}, + {() -> new WeakHashMap<>()} + }; } - @Test - public void capacityTestInitialCapacity() { - int initialCapacity = rnd.nextInt(2, 128); - List>> suppliers = List.of( - () -> new HashMap<>(initialCapacity), - () -> new HashMap<>(initialCapacity, 0.75f), - () -> new LinkedHashMap<>(initialCapacity), - () -> new LinkedHashMap<>(initialCapacity, 0.75f)); + @Test(dataProvider = "defaultCapacity") + public void defaultCapacity(Supplier> s) { + Map map = s.get(); + map.put("", ""); + assertEquals(capacity(map), 16); + } - for (Supplier> supplier : suppliers) { - HashMap map = supplier.get(); - assertNull(table(map)); + /* + * tests for requested capacity (int and int+float constructors) + */ - map.put(1, 1); - assertEquals(capacity(map), tableSizeFor(initialCapacity)); + @DataProvider(name = "requestedCapacity") + public Iterator requestedCapacityCases() { + ArrayList cases = new ArrayList<>(); + for (int i = 2; i < 128; i++) { + int cap = i; + cases.add(new Object[]{"rhm1", cap, (Supplier>) () -> new HashMap<>(cap)}); + cases.add(new Object[]{"rhm2", cap, (Supplier>) () -> new HashMap<>(cap, 0.75f)}); + cases.add(new Object[]{"rlm1", cap, (Supplier>) () -> new LinkedHashMap<>(cap)}); + cases.add(new Object[]{"rlm2", cap, (Supplier>) () -> new LinkedHashMap<>(cap, 0.75f)}); + cases.add(new Object[]{"rwm1", cap, (Supplier>) () -> new WeakHashMap<>(cap)}); + cases.add(new Object[]{"rwm2", cap, (Supplier>) () -> new WeakHashMap<>(cap, 0.75f)}); } + return cases.iterator(); + } + + @Test(dataProvider = "requestedCapacity") + public void requestedCapacity(String label, int cap, Supplier> s) { + Map map = s.get(); + map.put("", ""); + assertEquals(capacity(map), tableSizeFor(cap)); + } + + /* + * Tests for capacity after map is populated with a given number N of mappings. + * Maps are populated using a copy constructor on a map with N mappings, + * other constructors followed by N put() calls, and other constructors followed + * by putAll() on a map with N mappings. + * + * String labels encode the test case for ease of diagnosis if one of the test cases fails. + * For example, "plm2pn" is "populated LinkedHashMap, 2-arg constructor, followed by putN". + */ + + // helper method for one populated capacity case, to provide target types for lambdas + Object[] pcc(String label, + int size, + int expectedCapacity, + Supplier> supplier, + Consumer> consumer) { + return new Object[]{label, size, expectedCapacity, supplier, consumer}; + } + + List genPopulatedCapacityCases(int size, int cap) { + return Arrays.asList( + pcc("phmcpy", size, cap, () -> new HashMap<>(makeMap(size)), map -> { }), + pcc("phm0pn", size, cap, () -> new HashMap<>(), map -> { putN(map, size); }), + pcc("phm1pn", size, cap, () -> new HashMap<>(cap), map -> { putN(map, size); }), + pcc("phm2pn", size, cap, () -> new HashMap<>(cap, 0.75f), map -> { putN(map, size); }), + pcc("phm0pa", size, cap, () -> new HashMap<>(), map -> { map.putAll(makeMap(size)); }), + pcc("phm1pa", size, cap, () -> new HashMap<>(cap), map -> { map.putAll(makeMap(size)); }), + pcc("phm2pa", size, cap, () -> new HashMap<>(cap, 0.75f), map -> { map.putAll(makeMap(size)); }), + + pcc("plmcpy", size, cap, () -> new LinkedHashMap<>(makeMap(size)), map -> { }), + pcc("plm0pn", size, cap, () -> new LinkedHashMap<>(), map -> { putN(map, size); }), + pcc("plm1pn", size, cap, () -> new LinkedHashMap<>(cap), map -> { putN(map, size); }), + pcc("plm2pn", size, cap, () -> new LinkedHashMap<>(cap, 0.75f), map -> { putN(map, size); }), + pcc("plm0pa", size, cap, () -> new LinkedHashMap<>(), map -> { map.putAll(makeMap(size)); }), + pcc("plm1pa", size, cap, () -> new LinkedHashMap<>(cap), map -> { map.putAll(makeMap(size)); }), + pcc("plm2pa", size, cap, () -> new LinkedHashMap<>(cap, 0.75f), map -> { map.putAll(makeMap(size)); }), + + pcc("pwmcpy", size, cap, () -> new WeakHashMap<>(makeMap(size)), map -> { }), + pcc("pwm0pn", size, cap, () -> new WeakHashMap<>(), map -> { putN(map, size); }), + pcc("pwm1pn", size, cap, () -> new WeakHashMap<>(cap), map -> { putN(map, size); }), + pcc("pwm2pn", size, cap, () -> new WeakHashMap<>(cap, 0.75f), map -> { putN(map, size); }), + pcc("pwm0pa", size, cap, () -> new WeakHashMap<>(), map -> { map.putAll(makeMap(size)); }), + pcc("pwm1pa", size, cap, () -> new WeakHashMap<>(cap), map -> { map.putAll(makeMap(size)); }), + pcc("pwm2pa", size, cap, () -> new WeakHashMap<>(cap, 0.75f), map -> { map.putAll(makeMap(size)); }) + ); + } + + List genFakePopulatedCapacityCases(int size, int cap) { + return Arrays.asList( + pcc("fhmcpy", size, cap, () -> new HashMap<>(fakeMap(size)), map -> { }), + pcc("fhm0pa", size, cap, () -> new HashMap<>(), map -> { map.putAll(fakeMap(size)); }), + pcc("fhm1pa", size, cap, () -> new HashMap<>(cap), map -> { map.putAll(fakeMap(size)); }), + pcc("fhm2pa", size, cap, () -> new HashMap<>(cap, 0.75f), map -> { map.putAll(fakeMap(size)); }), + + pcc("flmcpy", size, cap, () -> new LinkedHashMap<>(fakeMap(size)), map -> { }), + pcc("flm0pa", size, cap, () -> new LinkedHashMap<>(), map -> { map.putAll(fakeMap(size)); }), + pcc("flm1pa", size, cap, () -> new LinkedHashMap<>(cap), map -> { map.putAll(fakeMap(size)); }), + pcc("flm2pa", size, cap, () -> new LinkedHashMap<>(cap, 0.75f), map -> { map.putAll(fakeMap(size)); }), + + pcc("fwmcpy", size, cap, () -> new WeakHashMap<>(fakeMap(size)), map -> { }), + // pcc("fwm0pa", size, cap, () -> new WeakHashMap<>(), map -> { map.putAll(fakeMap(size)); }), // see note + pcc("fwm1pa", size, cap, () -> new WeakHashMap<>(cap), map -> { map.putAll(fakeMap(size)); }), + pcc("fwm2pa", size, cap, () -> new WeakHashMap<>(cap, 0.75f), map -> { map.putAll(fakeMap(size)); }) + ); + + // Test case "fwm0pa" is commented out because WeakHashMap uses a different allocation + // policy from the other map implementations: it deliberately under-allocates in this case. + } + + @DataProvider(name = "populatedCapacity") + public Iterator populatedCapacityCases() { + ArrayList cases = new ArrayList<>(); + cases.addAll(genPopulatedCapacityCases(11, 16)); + cases.addAll(genPopulatedCapacityCases(12, 16)); + cases.addAll(genPopulatedCapacityCases(13, 32)); + cases.addAll(genPopulatedCapacityCases(64, 128)); + + // numbers in this range are truncated by a float computation with 0.75f + // but can get an exact result with a double computation with 0.75d + cases.addAll(genFakePopulatedCapacityCases(25165824, 33554432)); + cases.addAll(genFakePopulatedCapacityCases(25165825, 67108864)); + cases.addAll(genFakePopulatedCapacityCases(25165826, 67108864)); + + return cases.iterator(); } + + @Test(dataProvider = "populatedCapacity") + public void populatedCapacity(String label, // unused, included for diagnostics + int size, // unused, included for diagnostics + int expectedCapacity, + Supplier> s, + Consumer> c) { + Map map = s.get(); + c.accept(map); + assertEquals(capacity(map), expectedCapacity); + } + } diff --git a/test/jdk/java/util/Locale/LSRDataTest.java b/test/jdk/java/util/Locale/LSRDataTest.java index 81edf48b9b0466cc84512c53c8deda24b7123fa6..f32642981b5230d0d411cd72637e85398c7019d7 100644 --- a/test/jdk/java/util/Locale/LSRDataTest.java +++ b/test/jdk/java/util/Locale/LSRDataTest.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 @@ -52,11 +52,11 @@ public class LSRDataTest { private static final Map> multiLangEquivsMap = new HashMap<>(); private static final Map regionVariantEquivMap = new HashMap<>(); - // path to the lsr file from the make folder, this test relies on the - // relative path to the file in the make folder, considering - // test and make will always exist in the same jdk layout + // path to the lsr file from the data folder, this test relies on the + // relative path to the file in the data folder, considering + // test and src/.../data will always exist in the same jdk layout private static final String LSR_FILE_PATH = System.getProperty("test.src", ".") - + "/../../../../../make/data/lsrdata/language-subtag-registry.txt"; + + "/../../../../../src/java.base/share/data/lsrdata/language-subtag-registry.txt"; public static void main(String[] args) throws IOException { diff --git a/test/jdk/java/util/Properties/PropertiesStoreTest.java b/test/jdk/java/util/Properties/PropertiesStoreTest.java index da2be3b7cb57c3bae386809de855add9156f6b94..ab58ea789035dbebbbf25734304709fca97e3c07 100644 --- a/test/jdk/java/util/Properties/PropertiesStoreTest.java +++ b/test/jdk/java/util/Properties/PropertiesStoreTest.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 @@ -37,21 +37,28 @@ import java.time.format.DateTimeParseException; import java.util.ArrayList; import java.util.Arrays; import java.util.Comparator; +import java.util.HashSet; import java.util.List; +import java.util.Locale; import java.util.Map; import java.util.Properties; import java.util.Set; import java.util.TreeSet; +import java.util.stream.Collectors; /* * @test * @summary tests the order in which the Properties.store() method writes out the properties - * @bug 8231640 - * @run testng PropertiesStoreTest + * @bug 8231640 8282023 + * @run testng/othervm PropertiesStoreTest */ public class PropertiesStoreTest { private static final String DATE_FORMAT_PATTERN = "EEE MMM dd HH:mm:ss zzz uuuu"; + // use a neutral locale, since when the date comment was written by Properties.store(...), + // it internally calls the Date.toString() which always writes in a locale insensitive manner + private static final DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern(DATE_FORMAT_PATTERN, Locale.ROOT); + private static final Locale PREV_LOCALE = Locale.getDefault(); @DataProvider(name = "propsProvider") private Object[][] createProps() { @@ -91,6 +98,26 @@ public class PropertiesStoreTest { }; } + /** + * Returns a {@link Locale} to use for testing + */ + @DataProvider(name = "localeProvider") + private Object[][] provideLocales() { + // pick a non-english locale for testing + Set locales = Arrays.stream(Locale.getAvailableLocales()) + .filter(l -> !l.getLanguage().isEmpty() && !l.getLanguage().equals("en")) + .limit(1) + .collect(Collectors.toCollection(HashSet::new)); + locales.add(Locale.getDefault()); // always test the default locale + locales.add(Locale.US); // guaranteed to be present + locales.add(Locale.ROOT); // guaranteed to be present + + // return the chosen locales + return locales.stream() + .map(m -> new Locale[] {m}) + .toArray(n -> new Object[n][0]); + } + /** * Tests that the {@link Properties#store(Writer, String)} API writes out the properties * in the expected order @@ -153,29 +180,45 @@ public class PropertiesStoreTest { /** * Tests that {@link Properties#store(Writer, String)} writes out a proper date comment */ - @Test - public void testStoreWriterDateComment() throws Exception { - final Properties props = new Properties(); - props.setProperty("a", "b"); - final Path tmpFile = Files.createTempFile("8231640", "props"); - try (final Writer writer = Files.newBufferedWriter(tmpFile)) { - props.store(writer, null); + @Test(dataProvider = "localeProvider") + public void testStoreWriterDateComment(final Locale testLocale) throws Exception { + // switch the default locale to the one being tested + Locale.setDefault(testLocale); + System.out.println("Using locale: " + testLocale + " for Properties#store(Writer) test"); + try { + final Properties props = new Properties(); + props.setProperty("a", "b"); + final Path tmpFile = Files.createTempFile("8231640", "props"); + try (final Writer writer = Files.newBufferedWriter(tmpFile)) { + props.store(writer, null); + } + testDateComment(tmpFile); + } finally { + // reset to the previous one + Locale.setDefault(PREV_LOCALE); } - testDateComment(tmpFile); } /** * Tests that {@link Properties#store(OutputStream, String)} writes out a proper date comment */ - @Test - public void testStoreOutputStreamDateComment() throws Exception { - final Properties props = new Properties(); - props.setProperty("a", "b"); - final Path tmpFile = Files.createTempFile("8231640", "props"); - try (final Writer writer = Files.newBufferedWriter(tmpFile)) { - props.store(writer, null); + @Test(dataProvider = "localeProvider") + public void testStoreOutputStreamDateComment(final Locale testLocale) throws Exception { + // switch the default locale to the one being tested + Locale.setDefault(testLocale); + System.out.println("Using locale: " + testLocale + " for Properties#store(OutputStream) test"); + try { + final Properties props = new Properties(); + props.setProperty("a", "b"); + final Path tmpFile = Files.createTempFile("8231640", "props"); + try (final Writer writer = Files.newBufferedWriter(tmpFile)) { + props.store(writer, null); + } + testDateComment(tmpFile); + } finally { + // reset to the previous one + Locale.setDefault(PREV_LOCALE); } - testDateComment(tmpFile); } /** @@ -199,7 +242,7 @@ public class PropertiesStoreTest { Assert.fail("No comment line found in the stored properties file " + file); } try { - DateTimeFormatter.ofPattern(DATE_FORMAT_PATTERN).parse(comment); + FORMATTER.parse(comment); } catch (DateTimeParseException pe) { Assert.fail("Unexpected date comment: " + comment, pe); } diff --git a/test/jdk/java/util/Properties/StoreReproducibilityTest.java b/test/jdk/java/util/Properties/StoreReproducibilityTest.java index 5f865c29328239d3f3ddb537913b9214a57ac699..c4b1853a1d6abb715f95c50c25987237e370367a 100644 --- a/test/jdk/java/util/Properties/StoreReproducibilityTest.java +++ b/test/jdk/java/util/Properties/StoreReproducibilityTest.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 @@ import java.util.TimeZone; /* * @test * @summary Tests that the Properties.store() APIs generate output that is reproducible - * @bug 8231640 + * @bug 8231640 8282023 * @library /test/lib * @run driver StoreReproducibilityTest */ @@ -52,8 +52,8 @@ public class StoreReproducibilityTest { private static final String DATE_FORMAT_PATTERN = "EEE MMM dd HH:mm:ss zzz uuuu"; private static final String SYS_PROP_JAVA_PROPERTIES_DATE = "java.properties.date"; - private static final DateTimeFormatter reproducibleDateTimeFormatter = DateTimeFormatter.ofPattern(DATE_FORMAT_PATTERN) - .withLocale(Locale.ROOT).withZone(ZoneOffset.UTC); + private static final DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern(DATE_FORMAT_PATTERN, Locale.ROOT) + .withZone(ZoneOffset.UTC); public static void main(final String[] args) throws Exception { // no security manager enabled @@ -88,7 +88,7 @@ public class StoreReproducibilityTest { */ private static void testWithoutSecurityManager() throws Exception { final List storedFiles = new ArrayList<>(); - final String sysPropVal = reproducibleDateTimeFormatter.format(Instant.ofEpochSecond(243535322)); + final String sysPropVal = FORMATTER.format(Instant.ofEpochSecond(243535322)); for (int i = 0; i < 5; i++) { final Path tmpFile = Files.createTempFile("8231640", ".props"); storedFiles.add(tmpFile); @@ -130,7 +130,7 @@ public class StoreReproducibilityTest { }; """)); final List storedFiles = new ArrayList<>(); - final String sysPropVal = reproducibleDateTimeFormatter.format(Instant.ofEpochSecond(1234342423)); + final String sysPropVal = FORMATTER.format(Instant.ofEpochSecond(1234342423)); for (int i = 0; i < 5; i++) { final Path tmpFile = Files.createTempFile("8231640", ".props"); storedFiles.add(tmpFile); @@ -174,7 +174,7 @@ public class StoreReproducibilityTest { }; """)); final List storedFiles = new ArrayList<>(); - final String sysPropVal = reproducibleDateTimeFormatter.format(Instant.ofEpochSecond(1234342423)); + final String sysPropVal = FORMATTER.format(Instant.ofEpochSecond(1234342423)); for (int i = 0; i < 5; i++) { final Path tmpFile = Files.createTempFile("8231640", ".props"); storedFiles.add(tmpFile); @@ -425,10 +425,10 @@ public class StoreReproducibilityTest { System.out.println("Found date comment " + dateComment + " in file " + destFile); final Date parsedDate; try { - Instant instant = Instant.from(DateTimeFormatter.ofPattern(DATE_FORMAT_PATTERN).parse(dateComment)); + Instant instant = Instant.from(FORMATTER.parse(dateComment)); parsedDate = new Date(instant.toEpochMilli()); } catch (DateTimeParseException pe) { - throw new RuntimeException("Unexpected date " + dateComment + " in stored properties " + destFile); + throw new RuntimeException("Unexpected date " + dateComment + " in stored properties " + destFile, pe); } if (!parsedDate.after(date)) { throw new RuntimeException("Expected date comment " + dateComment + " to be after " + date diff --git a/test/jdk/java/util/Random/T8282144.java b/test/jdk/java/util/Random/T8282144.java new file mode 100644 index 0000000000000000000000000000000000000000..4a0218602f27ec84b3510ec3f761a9df828626c7 --- /dev/null +++ b/test/jdk/java/util/Random/T8282144.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. + */ + +import java.util.random.*; +import jdk.internal.util.random.RandomSupport; + +/** + * @test + * @summary RandomSupport.convertSeedBytesToLongs sign extension overwrites previous bytes. + * @bug 8282144 + * @modules java.base/jdk.internal.util.random + * @run main T8282144 + * @key randomness + */ + + +public class T8282144 { + public static void main(String[] args) { + RandomGenerator rng = RandomGeneratorFactory.of("L64X128MixRandom").create(42); + + for (int i = 1; i < 8; i++) { + byte[] seed = new byte[i]; + + for (int j = 0; j < 10; j++) { + rng.nextBytes(seed); + + long[] existing = RandomSupport.convertSeedBytesToLongs(seed, 1, 1); + long[] testing = convertSeedBytesToLongsFixed(seed, 1, 1); + + for (int k = 0; k < existing.length; k++) { + if (existing[k] != testing[k]) { + throw new RuntimeException("convertSeedBytesToLongs incorrect"); + } + } + } + } + } + + + public static long[] convertSeedBytesToLongsFixed(byte[] seed, int n, int z) { + final long[] result = new long[n]; + final int m = Math.min(seed.length, n << 3); + + // Distribute seed bytes into the words to be formed. + for (int j = 0; j < m; j++) { + result[j >> 3] = (result[j >> 3] << 8) | (seed[j] & 0xff); + } + + return result; + } +} diff --git a/test/jdk/java/util/ResourceBundle/exeNullCallerResourceBundle/NullCallerResourceBundle.java b/test/jdk/java/util/ResourceBundle/exeNullCallerResourceBundle/NullCallerResourceBundle.java new file mode 100644 index 0000000000000000000000000000000000000000..edbcf3ba3164b3a9a1793c8bff8d8fe525f203b8 --- /dev/null +++ b/test/jdk/java/util/ResourceBundle/exeNullCallerResourceBundle/NullCallerResourceBundle.java @@ -0,0 +1,83 @@ +/* + * 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 8280902 + * @summary Test uses custom launcher that starts VM using JNI that verifies + * ResourceBundle::getBundle with null caller class functions properly + * using the system class loader unnamed module. The custom launcher + * creates a properties file and passes the VM option to the JNI + * functionality for the resource lookup. + * @library /test/lib + * @requires os.family != "aix" + * @run main/native NullCallerResourceBundle + */ + +// Test disabled on AIX since we cannot invoke the JVM on the primordial thread. + +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.Properties; +import jdk.test.lib.Platform; +import jdk.test.lib.process.OutputAnalyzer; + +public class NullCallerResourceBundle { + public static void main(String[] args) throws IOException { + + // build a properties file for the native test + var propPath = Path.of(System.getProperty("test.classes"), "NullCallerResource.properties"); + try (var stream = Files.newOutputStream(propPath)) { + var props = new Properties(); + props.put("message", "Hello!"); + props.save(stream, "Test property list"); + } + + var launcher = Path.of(System.getProperty("test.nativepath"), "NullCallerResourceBundle"); + var classpathAppend = "-Djava.class.path=" + System.getProperty("test.classes"); + var pb = new ProcessBuilder(launcher.toString(), classpathAppend); + var env = pb.environment(); + + var libDir = Platform.libDir().toString(); + var vmDir = Platform.jvmLibDir().toString(); + + // set up shared library path + var sharedLibraryPathEnvName = Platform.sharedLibraryPathVariableName(); + env.compute(sharedLibraryPathEnvName, + (k, v) -> (v == null) ? libDir : v + File.pathSeparator + libDir); + env.compute(sharedLibraryPathEnvName, + (k, v) -> (v == null) ? vmDir : v + File.pathSeparator + vmDir); + + System.out.println("Launching: " + launcher + " shared library path: " + + env.get(sharedLibraryPathEnvName)); + new OutputAnalyzer(pb.start()) + .outputTo(System.out) + .errorTo(System.err) + .shouldHaveExitValue(0); + } + +} + diff --git a/test/jdk/java/util/ResourceBundle/exeNullCallerResourceBundle/exeNullCallerResourceBundle.c b/test/jdk/java/util/ResourceBundle/exeNullCallerResourceBundle/exeNullCallerResourceBundle.c new file mode 100644 index 0000000000000000000000000000000000000000..309873df795866cd9a0303143a94002a60282a63 --- /dev/null +++ b/test/jdk/java/util/ResourceBundle/exeNullCallerResourceBundle/exeNullCallerResourceBundle.c @@ -0,0 +1,102 @@ +/* + * 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 "jni.h" +#undef NDEBUG +#include "assert.h" +#include "string.h" + + +/* + * The java test running this native test passes in an argument to provide as + * an option for the configuration of the JVM. The system classpath has the + * classpath of the java test appended so it can pick up the resource that + * was created by the java part of the test. + */ +int main(int argc, char** args) { + JavaVM *jvm; + JNIEnv *env; + JavaVMInitArgs vm_args; + JavaVMOption options[1]; + jint rc; + + assert(argc == 2); + options[0].optionString = args[1]; + + vm_args.version = JNI_VERSION_1_2; + vm_args.nOptions = 1; + vm_args.options = options; + + if ((rc = JNI_CreateJavaVM(&jvm, (void**)&env, &vm_args)) != JNI_OK) { + printf("ERROR: cannot create VM.\n"); + exit(-1); + } + + // b = ResourceBundle.getBundle("NullCallerResource"); + jclass class_ResourceBundle = (*env)->FindClass(env, "java/util/ResourceBundle"); + assert(class_ResourceBundle != NULL); + jmethodID mid_ResourceBundle_getBundle = (*env)->GetStaticMethodID(env, class_ResourceBundle, "getBundle", "(Ljava/lang/String;)Ljava/util/ResourceBundle;" ); + assert(mid_ResourceBundle_getBundle != NULL); + jobject resourceName = (*env)->NewStringUTF(env, "NullCallerResource"); + assert(resourceName != NULL); + jobject b = (*env)->CallStaticObjectMethod(env, class_ResourceBundle, mid_ResourceBundle_getBundle, resourceName); + if ((*env)->ExceptionOccurred(env) != NULL) { + printf("ERROR: Exception was thrown calling ResourceBundle::getBundle.\n"); + (*env)->ExceptionDescribe(env); + exit(-1); + } + + // msg = b.getString("message"); + jmethodID mid_ResourceBundle_getString = (*env)->GetMethodID(env, class_ResourceBundle, "getString", "(Ljava/lang/String;)Ljava/lang/String;" ); + assert(mid_ResourceBundle_getString != NULL); + jobject key = (*env)->NewStringUTF(env, "message"); + jobject msg =(*env)->CallObjectMethod(env, b, mid_ResourceBundle_getString, key); + if ((*env)->ExceptionOccurred(env) != NULL) { + printf("ERROR: Exception was thrown calling ResourceBundle::getString.\n"); + (*env)->ExceptionDescribe(env); + exit(-1); + } + assert(msg != NULL); + + // check the message + const char* cstr = (*env)->GetStringUTFChars(env, msg, NULL); + assert(cstr != NULL); + assert(strcmp(cstr,"Hello!") == 0); + + // ResourceBundle.clearCache() + jmethodID mid_ResourceBundle_clearCache = (*env)->GetStaticMethodID(env, class_ResourceBundle, "clearCache", "()V" ); + assert(mid_ResourceBundle_clearCache != NULL); + (*env)->CallStaticVoidMethod(env, class_ResourceBundle, mid_ResourceBundle_clearCache); + if ((*env)->ExceptionOccurred(env) != NULL) { + printf("ERROR: Exception was thrown calling ResourceBundle::clearCache.\n"); + (*env)->ExceptionDescribe(env); + exit(-1); + } + + (*jvm)->DestroyJavaVM(jvm); + return 0; +} + diff --git a/test/jdk/java/util/logging/TestAppletLoggerContext.java b/test/jdk/java/util/logging/TestAppletLoggerContext.java index 6fbe975b5e4339f80cce8575ae28ef6947110abb..b69497a626e4a7cba705642d8dd31031fbaddfe1 100644 --- a/test/jdk/java/util/logging/TestAppletLoggerContext.java +++ b/test/jdk/java/util/logging/TestAppletLoggerContext.java @@ -447,7 +447,7 @@ public class TestAppletLoggerContext { Logger logger4b = manager.getLogger(Logger.GLOBAL_LOGGER_NAME); assertNotNull(logger4); assertNotNull(logger4b); - expected = (System.getSecurityManager() == null ? global : global2);; + expected = (System.getSecurityManager() == null ? global : global2); assertEquals(logger4, expected); assertEquals(logger4b, expected); diff --git a/test/jdk/java/util/regex/RegExTest.java b/test/jdk/java/util/regex/RegExTest.java index f46ce327f03e44fbcd32345c7527434897d9da04..39c454ce4f446f2468f3dad079a2414a12749d16 100644 --- a/test/jdk/java/util/regex/RegExTest.java +++ b/test/jdk/java/util/regex/RegExTest.java @@ -4556,4 +4556,37 @@ public class RegExTest { Pattern.compile(pattern)); assertTrue(e.getMessage().contains("Bad intersection syntax")); } + + //This test is for 8281560 + @Test + public static void prematureHitEndInNFCCharProperty() { + var testInput = "a1a1"; + var pat1 = "(a+|1+)"; + var pat2 = "([a]+|[1]+)"; + + var matcher1 = Pattern.compile(pat1, Pattern.CANON_EQ).matcher(testInput); + var matcher2 = Pattern.compile(pat2, Pattern.CANON_EQ).matcher(testInput); + + ArrayList results1 = new ArrayList<>(); + ArrayList results2 = new ArrayList<>(); + + while (matcher1.find()) { + results1.add(matcher1.hitEnd()); + } + + while (matcher2.find()) { + results2.add(matcher2.hitEnd()); + } + + assertEquals(results1, results2); + } + + //This test is for 8281315 + @Test + public static void iOOBForCIBackrefs(){ + String line = "\ud83d\udc95\ud83d\udc95\ud83d\udc95"; + var pattern2 = Pattern.compile("(?i)(.)\\1{2,}"); + assertTrue(pattern2.matcher(line).find()); + } } + diff --git a/test/jdk/java/util/zip/CloseDeflaterTest.java b/test/jdk/java/util/zip/CloseDeflaterTest.java deleted file mode 100644 index 8aa4960f543628edc887c61a10a897373f38657f..0000000000000000000000000000000000000000 --- a/test/jdk/java/util/zip/CloseDeflaterTest.java +++ /dev/null @@ -1,147 +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 - * @bug 8193682 - * @summary Test Infinite loop while writing on closed GZipOutputStream , ZipOutputStream and JarOutputStream. - * @run testng CloseDeflaterTest - */ -import java.io.*; -import java.util.Random; -import java.util.jar.JarOutputStream; -import java.util.zip.GZIPOutputStream; -import java.util.zip.ZipOutputStream; -import java.util.zip.ZipEntry; - -import org.testng.annotations.BeforeTest; -import org.testng.annotations.DataProvider; -import org.testng.annotations.Test; -import static org.testng.Assert.fail; - - -public class CloseDeflaterTest { - - //number of bytes to write - private static final int INPUT_LENGTH= 512; - //OutputStream that will throw an exception during a write operation - private static OutputStream outStream = new OutputStream() { - @Override - public void write(byte[] b, int off, int len) throws IOException { - //throw exception during write - throw new IOException(); - } - @Override - public void write(byte b[]) throws IOException {} - @Override - public void write(int b) throws IOException {} - }; - private static byte[] inputBytes = new byte[INPUT_LENGTH]; - private static Random rand = new Random(); - - @DataProvider(name = "testgzipinput") - public Object[][] testGZipInput() { - //testGZip will close the GZipOutputStream using close() method when the boolean - //useCloseMethod is set to true and finish() method if the value is set to false - return new Object[][] { - { GZIPOutputStream.class, true }, - { GZIPOutputStream.class, false }, - }; - } - - @DataProvider(name = "testzipjarinput") - public Object[][] testZipAndJarInput() { - //testZipAndJarInput will perfrom write/closeEntry operations on JarOutputStream when the boolean - //useJar is set to true and on ZipOutputStream if the value is set to false - return new Object[][] { - { JarOutputStream.class, true }, - { ZipOutputStream.class, false }, - }; - } - - @BeforeTest - public void before_test() - { - //add inputBytes array with random bytes to write into Zip - rand.nextBytes(inputBytes); - } - - //Test for infinite loop by writing bytes to closed GZIPOutputStream - @Test(dataProvider = "testgzipinput") - public void testGZip(Class type, boolean useCloseMethod) throws IOException { - GZIPOutputStream zip = new GZIPOutputStream(outStream); - try { - zip.write(inputBytes, 0, INPUT_LENGTH); - //close zip - if(useCloseMethod) { - zip.close(); - } else { - zip.finish(); - } - } catch (IOException e) { - //expected - } - for (int i = 0; i < 3; i++) { - try { - //write on a closed GZIPOutputStream - zip.write(inputBytes, 0, INPUT_LENGTH); - fail("Deflater closed exception not thrown"); - } catch (NullPointerException e) { - //expected , Deflater has been closed exception - } - } - } - - //Test for infinite loop by writing bytes to closed ZipOutputStream/JarOutputStream - @Test(dataProvider = "testzipjarinput") - public void testZipCloseEntry(Class type,boolean useJar) throws IOException { - ZipOutputStream zip = null; - if(useJar) { - zip = new JarOutputStream(outStream); - } else { - zip = new ZipOutputStream(outStream); - } - try { - zip.putNextEntry(new ZipEntry("")); - } catch (IOException e) { - //expected to throw IOException since putNextEntry calls write method - } - try { - zip.write(inputBytes, 0, INPUT_LENGTH); - //close zip entry - zip.closeEntry(); - } catch (IOException e) { - //expected - } - for (int i = 0; i < 3; i++) { - try { - //write on a closed ZipOutputStream - zip.write(inputBytes, 0, INPUT_LENGTH); - fail("Deflater closed exception not thrown"); - } catch (NullPointerException e) { - //expected , Deflater has been closed exception - } - } - } - -} diff --git a/test/jdk/java/util/zip/CloseInflaterDeflaterTest.java b/test/jdk/java/util/zip/CloseInflaterDeflaterTest.java new file mode 100644 index 0000000000000000000000000000000000000000..4f0fafc8dbeddab48f98ab5618ab46dd513106b3 --- /dev/null +++ b/test/jdk/java/util/zip/CloseInflaterDeflaterTest.java @@ -0,0 +1,208 @@ +/* + * 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 + * @bug 8193682 8278794 + * @summary Test Infinite loop while writing on closed Deflater and Inflater. + * @run testng CloseInflaterDeflaterTest + */ +import java.io.*; +import java.util.Random; +import java.util.jar.JarOutputStream; +import java.util.zip.DeflaterInputStream; +import java.util.zip.DeflaterOutputStream; +import java.util.zip.GZIPOutputStream; +import java.util.zip.InflaterOutputStream; +import java.util.zip.ZipOutputStream; +import java.util.zip.ZipEntry; + +import org.testng.annotations.BeforeTest; +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; +import static org.testng.Assert.assertThrows; + + +public class CloseInflaterDeflaterTest { + + // Number of bytes to write/read from Deflater/Inflater + private static final int INPUT_LENGTH= 512; + // OutputStream that will throw an exception during a write operation + private static OutputStream outStream = new OutputStream() { + @Override + public void write(byte[] b, int off, int len) throws IOException { + throw new IOException(); + } + @Override + public void write(byte[] b) throws IOException {} + @Override + public void write(int b) throws IOException {} + }; + // InputStream that will throw an exception during a read operation + private static InputStream inStream = new InputStream() { + @Override + public int read(byte[] b, int off, int len) throws IOException { + throw new IOException(); + } + @Override + public int read(byte[] b) throws IOException { throw new IOException();} + @Override + public int read() throws IOException { throw new IOException();} + }; + // Input bytes for read/write operation + private static byte[] inputBytes = new byte[INPUT_LENGTH]; + // Random function to add bytes to inputBytes + private static Random rand = new Random(); + + /** + * DataProvider to specify whether to use close() or finish() of OutputStream + * + * @return Entry object indicating which method to use for closing OutputStream + */ + @DataProvider + public Object[][] testOutputStreams() { + return new Object[][] { + { true }, + { false }, + }; + } + + /** + * DataProvider to specify on which outputstream closeEntry() has to be called + * + * @return Entry object returning either JarOutputStream or ZipOutputStream + */ + @DataProvider + public Object[][] testZipAndJar() throws IOException{ + return new Object[][] { + { new JarOutputStream(outStream)}, + { new ZipOutputStream(outStream)}, + }; + } + + /** + * Add inputBytes array with random bytes to write into OutputStream + */ + @BeforeTest + public void before_test() + { + rand.nextBytes(inputBytes); + } + + /** + * Test for infinite loop by writing bytes to closed GZIPOutputStream + * + * @param useCloseMethod indicates whether to use Close() or finish() method + * @throws IOException if an error occurs + */ + @Test(dataProvider = "testOutputStreams") + public void testGZip(boolean useCloseMethod) throws IOException { + GZIPOutputStream gzip = new GZIPOutputStream(outStream); + gzip.write(inputBytes, 0, INPUT_LENGTH); + assertThrows(IOException.class, () -> { + // Close GZIPOutputStream + if (useCloseMethod) { + gzip.close(); + } else { + gzip.finish(); + } + }); + // Write on a closed GZIPOutputStream, closed Deflater IOException expected + assertThrows(NullPointerException.class , () -> gzip.write(inputBytes, 0, INPUT_LENGTH)); + } + + /** + * Test for infinite loop by writing bytes to closed DeflaterOutputStream + * + * @param useCloseMethod indicates whether to use Close() or finish() method + * @throws IOException if an error occurs + */ + @Test(dataProvider = "testOutputStreams") + public void testDeflaterOutputStream(boolean useCloseMethod) throws IOException { + DeflaterOutputStream def = new DeflaterOutputStream(outStream); + assertThrows(IOException.class , () -> def.write(inputBytes, 0, INPUT_LENGTH)); + assertThrows(IOException.class, () -> { + // Close DeflaterOutputStream + if (useCloseMethod) { + def.close(); + } else { + def.finish(); + } + }); + // Write on a closed DeflaterOutputStream, 'Deflater has been closed' NPE is expected + assertThrows(NullPointerException.class , () -> def.write(inputBytes, 0, INPUT_LENGTH)); + } + + /** + * Test for infinite loop by reading bytes from closed DeflaterInputStream + * + * @throws IOException if an error occurs + */ + @Test + public void testDeflaterInputStream() throws IOException { + DeflaterInputStream def = new DeflaterInputStream(inStream); + assertThrows(IOException.class , () -> def.read(inputBytes, 0, INPUT_LENGTH)); + // Close DeflaterInputStream + def.close(); + // Read from a closed DeflaterInputStream, closed Deflater IOException expected + assertThrows(IOException.class , () -> def.read(inputBytes, 0, INPUT_LENGTH)); + } + + /** + * Test for infinite loop by writing bytes to closed InflaterOutputStream + * + * @param useCloseMethod indicates whether to use Close() or finish() method + * @throws IOException if an error occurs + */ + @Test(dataProvider = "testOutputStreams") + public void testInflaterOutputStream(boolean useCloseMethod) throws IOException { + InflaterOutputStream inf = new InflaterOutputStream(outStream); + assertThrows(IOException.class , () -> inf.write(inputBytes, 0, INPUT_LENGTH)); + assertThrows(IOException.class , () -> { + // Close InflaterOutputStream + if (useCloseMethod) { + inf.close(); + } else { + inf.finish(); + } + }); + // Write on a closed InflaterOutputStream , closed Inflater IOException expected + assertThrows(IOException.class , () -> inf.write(inputBytes, 0, INPUT_LENGTH)); + } + + /** + * Test for infinite loop by writing bytes to closed ZipOutputStream/JarOutputStream + * + * @param zip will be the instance of either JarOutputStream or ZipOutputStream + * @throws IOException if an error occurs + */ + @Test(dataProvider = "testZipAndJar") + public void testZipCloseEntry(ZipOutputStream zip) throws IOException { + assertThrows(IOException.class , () -> zip.putNextEntry(new ZipEntry(""))); + zip.write(inputBytes, 0, INPUT_LENGTH); + assertThrows(IOException.class , () -> zip.closeEntry()); + // Write on a closed ZipOutputStream , 'Deflater has been closed' NPE is expected + assertThrows(NullPointerException.class , () -> zip.write(inputBytes, 0, INPUT_LENGTH)); + } + +} diff --git a/test/jdk/java/util/zip/ZipFile/GetInputStreamNPETest.java b/test/jdk/java/util/zip/ZipFile/GetInputStreamNPETest.java new file mode 100644 index 0000000000000000000000000000000000000000..ec7f0fc7d454d3f64f6ec6a93a989a75e159f498 --- /dev/null +++ b/test/jdk/java/util/zip/ZipFile/GetInputStreamNPETest.java @@ -0,0 +1,1055 @@ +/* + * 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.AfterTest; +import org.testng.annotations.BeforeTest; +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.Arrays; +import java.util.Formatter; +import java.util.jar.JarEntry; +import java.util.jar.JarFile; +import java.util.zip.ZipEntry; +import java.util.zip.ZipFile; + +import static org.testng.Assert.*; + +/** + * @test + * @bug 8280409 + * @summary Validate that Zip/JarFile::getInputStream will throw a NullPointerException + * @run testng/othervm GetInputStreamNPETest + */ +public class GetInputStreamNPETest { + // Name used to create a JAR with an invalid entry name + public static final Path INVALID_ENTRY_NAME_JAR = + Path.of("Invalid-EntryName.jar"); + // Name used to create a JAR with a valid entry name + public static final Path VALID_ENTRY_NAME_JAR = + Path.of("Valid-EntryName.jar"); + // Name used to create a JAR with an invalid entry name + public static final Path SIGNED_INVALID_ENTRY_NAME_JAR = + Path.of("Signed-Invalid-EntryName.jar"); + // Name used to create a JAR with a valid entry name + public static final Path SIGNED_VALID_ENTRY_NAME_JAR = + Path.of("Signed-Valid-EntryName.jar"); + // Value to change the "S" in "Singleton.class" to + public static final byte INVALID_UTF8_BYTE = (byte) 0x13; + // CEN offset to where "Singleton.class" filename starts + public static final int SINGLETON_CEN_FILENAME_OFFSET = 37; + // CEN filename which will be modified to validate a ZipException is thrown + public static final String CEN_FILENAME_TO_MODIFY = "javax/inject/Singleton.class"; + // Zip Entry name that does not exist within the JarFile + public static final String ZIP_ENTRY_THAT_DOES_NOT_EXIST = "org/gotham/Batcave.class"; + + /** + * Byte array representing a valid jar file prior modifying a filename in the + * CEN. + * The "Valid-EntryName.jar" jar file was created via: + *

+     *     {@code
+     *        jar cvf Valid-EntryName.jar javax/inject/Singleton.class
+     *        added manifest
+     *        adding: javax/inject/Singleton.class(in = 359) (out= 221)(deflated 38%)
+     *     }
+     * 
+ * Its contents are: + *
+     *     {@code
+     *        jar tvf Valid-EntryName.jar
+     *         0 Wed Jan 26 14:27:26 EST 2022 META-INF/
+     *        66 Wed Jan 26 14:27:26 EST 2022 META-INF/MANIFEST.MF
+     *       359 Mon Jan 24 22:11:24 EST 2011 javax/inject/Singleton.class
+     *     }
+     * 
+ * The ByteArray was created by: + *
+     *  {@code
+     *     var jar = Files.readAllBytes("Valid-EntryName.jar");
+     *     var validEntryName = createByteArray(fooJar, "VALID_ENTRY_NAME");
+     *  }
+     * 
+ */ + public static byte[] VALID_ENTRY_NAME = { + (byte) 0x50, (byte) 0x4b, (byte) 0x3, (byte) 0x4, (byte) 0x14, + (byte) 0x0, (byte) 0x8, (byte) 0x8, (byte) 0x8, (byte) 0x0, + (byte) 0x6d, (byte) 0x73, (byte) 0x3a, (byte) 0x54, (byte) 0x0, + (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, + (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, + (byte) 0x0, (byte) 0x9, (byte) 0x0, (byte) 0x4, (byte) 0x0, + (byte) 0x4d, (byte) 0x45, (byte) 0x54, (byte) 0x41, (byte) 0x2d, + (byte) 0x49, (byte) 0x4e, (byte) 0x46, (byte) 0x2f, (byte) 0xfe, + (byte) 0xca, (byte) 0x0, (byte) 0x0, (byte) 0x3, (byte) 0x0, + (byte) 0x50, (byte) 0x4b, (byte) 0x7, (byte) 0x8, (byte) 0x0, + (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x2, (byte) 0x0, + (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, + (byte) 0x0, (byte) 0x50, (byte) 0x4b, (byte) 0x3, (byte) 0x4, + (byte) 0x14, (byte) 0x0, (byte) 0x8, (byte) 0x8, (byte) 0x8, + (byte) 0x0, (byte) 0x6d, (byte) 0x73, (byte) 0x3a, (byte) 0x54, + (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, + (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, + (byte) 0x0, (byte) 0x0, (byte) 0x14, (byte) 0x0, (byte) 0x0, + (byte) 0x0, (byte) 0x4d, (byte) 0x45, (byte) 0x54, (byte) 0x41, + (byte) 0x2d, (byte) 0x49, (byte) 0x4e, (byte) 0x46, (byte) 0x2f, + (byte) 0x4d, (byte) 0x41, (byte) 0x4e, (byte) 0x49, (byte) 0x46, + (byte) 0x45, (byte) 0x53, (byte) 0x54, (byte) 0x2e, (byte) 0x4d, + (byte) 0x46, (byte) 0xf3, (byte) 0x4d, (byte) 0xcc, (byte) 0xcb, + (byte) 0x4c, (byte) 0x4b, (byte) 0x2d, (byte) 0x2e, (byte) 0xd1, + (byte) 0xd, (byte) 0x4b, (byte) 0x2d, (byte) 0x2a, (byte) 0xce, + (byte) 0xcc, (byte) 0xcf, (byte) 0xb3, (byte) 0x52, (byte) 0x30, + (byte) 0xd4, (byte) 0x33, (byte) 0xe0, (byte) 0xe5, (byte) 0x72, + (byte) 0x2e, (byte) 0x4a, (byte) 0x4d, (byte) 0x2c, (byte) 0x49, + (byte) 0x4d, (byte) 0xd1, (byte) 0x75, (byte) 0xaa, (byte) 0x4, + (byte) 0xa, (byte) 0x98, (byte) 0xe8, (byte) 0x19, (byte) 0xe8, + (byte) 0x19, (byte) 0x2a, (byte) 0x68, (byte) 0xf8, (byte) 0x17, + (byte) 0x25, (byte) 0x26, (byte) 0xe7, (byte) 0xa4, (byte) 0x2a, + (byte) 0x38, (byte) 0xe7, (byte) 0x17, (byte) 0x15, (byte) 0xe4, + (byte) 0x17, (byte) 0x25, (byte) 0x96, (byte) 0x0, (byte) 0x15, + (byte) 0x6b, (byte) 0xf2, (byte) 0x72, (byte) 0xf1, (byte) 0x72, + (byte) 0x1, (byte) 0x0, (byte) 0x50, (byte) 0x4b, (byte) 0x7, + (byte) 0x8, (byte) 0xf4, (byte) 0x59, (byte) 0xdc, (byte) 0xa6, + (byte) 0x42, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x42, + (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x50, (byte) 0x4b, + (byte) 0x3, (byte) 0x4, (byte) 0x14, (byte) 0x0, (byte) 0x8, + (byte) 0x8, (byte) 0x8, (byte) 0x0, (byte) 0x6c, (byte) 0xb1, + (byte) 0x38, (byte) 0x3e, (byte) 0x0, (byte) 0x0, (byte) 0x0, + (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, + (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x1c, + (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x6a, (byte) 0x61, + (byte) 0x76, (byte) 0x61, (byte) 0x78, (byte) 0x2f, (byte) 0x69, + (byte) 0x6e, (byte) 0x6a, (byte) 0x65, (byte) 0x63, (byte) 0x74, + (byte) 0x2f, (byte) 0x53, (byte) 0x69, (byte) 0x6e, (byte) 0x67, + (byte) 0x6c, (byte) 0x65, (byte) 0x74, (byte) 0x6f, (byte) 0x6e, + (byte) 0x2e, (byte) 0x63, (byte) 0x6c, (byte) 0x61, (byte) 0x73, + (byte) 0x73, (byte) 0x85, (byte) 0x90, (byte) 0x4d, (byte) 0x4b, + (byte) 0x82, (byte) 0x41, (byte) 0x10, (byte) 0xc7, (byte) 0xff, + (byte) 0xa3, (byte) 0xd9, (byte) 0x63, (byte) 0x56, (byte) 0xe6, + (byte) 0x21, (byte) 0x5, (byte) 0x4f, (byte) 0xda, (byte) 0xc5, + (byte) 0x63, (byte) 0x4b, (byte) 0xe7, (byte) 0x4e, (byte) 0x41, + (byte) 0x6, (byte) 0x81, (byte) 0xa5, (byte) 0x3c, (byte) 0x5a, + (byte) 0xf7, (byte) 0x75, (byte) 0x1b, (byte) 0x64, (byte) 0x65, + (byte) 0xdd, (byte) 0x8d, (byte) 0xdc, (byte) 0x47, (byte) 0xea, + (byte) 0xab, (byte) 0x79, (byte) 0xe8, (byte) 0x3, (byte) 0xf4, + (byte) 0xa1, (byte) 0xc4, (byte) 0xd9, (byte) 0xe, (byte) 0x4a, + (byte) 0x20, (byte) 0x34, (byte) 0x30, (byte) 0x2f, (byte) 0xcc, + (byte) 0xfc, (byte) 0x66, (byte) 0x98, (byte) 0x99, (byte) 0x9f, + (byte) 0xcd, (byte) 0xfa, (byte) 0x1b, (byte) 0xc0, (byte) 0xd, + (byte) 0x1a, (byte) 0x84, (byte) 0x2c, (byte) 0x7f, (byte) 0x79, + (byte) 0x9e, (byte) 0x3c, (byte) 0x3e, (byte) 0xf5, (byte) 0x9, + (byte) 0x8d, (byte) 0xb9, (byte) 0x5e, (byte) 0x69, (byte) 0xe5, + (byte) 0xb4, (byte) 0x9f, (byte) 0xa9, (byte) 0xe1, (byte) 0x74, + (byte) 0xce, (byte) 0x26, (byte) 0x12, (byte) 0x3a, (byte) 0xfb, + (byte) 0x94, (byte) 0xf6, (byte) 0x3e, (byte) 0x44, (byte) 0x1d, + (byte) 0x6d, (byte) 0xf0, (byte) 0xea, (byte) 0x6e, (byte) 0x17, + (byte) 0x12, (byte) 0x5a, (byte) 0x89, (byte) 0xf8, (byte) 0x54, + (byte) 0xd6, (byte) 0xa7, (byte) 0x6, (byte) 0x35, (byte) 0xb6, + (byte) 0x7e, (byte) 0xe6, (byte) 0x38, (byte) 0xa6, (byte) 0x42, + (byte) 0x65, (byte) 0xa5, (byte) 0x5d, (byte) 0xc1, (byte) 0x19, + (byte) 0x4a, (byte) 0x19, (byte) 0xca, (byte) 0x19, (byte) 0x8e, + (byte) 0x8, (byte) 0x57, (byte) 0x83, (byte) 0x83, (byte) 0xc3, + (byte) 0xee, (byte) 0x83, (byte) 0x29, (byte) 0x16, (byte) 0xec, + (byte) 0x23, (byte) 0xbf, (byte) 0xdd, (byte) 0x12, (byte) 0xba, + (byte) 0x87, (byte) 0x99, (byte) 0x9c, (byte) 0xa3, (byte) 0x10, + (byte) 0x12, (byte) 0x9, (byte) 0xd2, (byte) 0xfb, (byte) 0x7, + (byte) 0x19, (byte) 0x5, (byte) 0x67, (byte) 0xcd, (byte) 0x97, + (byte) 0x80, (byte) 0x97, (byte) 0x83, (byte) 0xbf, (byte) 0xab, + (byte) 0x99, (byte) 0xf0, (byte) 0xce, (byte) 0x92, (byte) 0x6e, + (byte) 0xe7, (byte) 0x85, (byte) 0x70, (byte) 0xb, (byte) 0x7e, + (byte) 0xb5, (byte) 0x4b, (byte) 0x3b, (byte) 0x75, (byte) 0xbc, + (byte) 0xbf, (byte) 0x65, (byte) 0x49, (byte) 0xa8, (byte) 0xef, + (byte) 0xf6, (byte) 0xbf, (byte) 0x4e, (byte) 0xbd, (byte) 0x84, + (byte) 0xda, (byte) 0x38, (byte) 0x14, (byte) 0x1f, (byte) 0x86, + (byte) 0x1f, (byte) 0xac, (byte) 0xe3, (byte) 0x1e, (byte) 0xa1, + (byte) 0x8a, (byte) 0x63, (byte) 0xc8, (byte) 0xc3, (byte) 0x90, + (byte) 0xa4, (byte) 0x84, (byte) 0x8b, (byte) 0x5f, (byte) 0x5b, + (byte) 0xc7, (byte) 0xb9, (byte) 0xf8, (byte) 0x26, (byte) 0xca, + (byte) 0x38, (byte) 0x13, (byte) 0x7f, (byte) 0x22, (byte) 0x5a, + (byte) 0x13, (byte) 0xa6, (byte) 0xc2, (byte) 0x38, (byte) 0x5, + (byte) 0x6d, (byte) 0x1, (byte) 0x50, (byte) 0x4b, (byte) 0x7, + (byte) 0x8, (byte) 0x5a, (byte) 0xf1, (byte) 0x0, (byte) 0x98, + (byte) 0xdd, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x67, + (byte) 0x1, (byte) 0x0, (byte) 0x0, (byte) 0x50, (byte) 0x4b, + (byte) 0x1, (byte) 0x2, (byte) 0x14, (byte) 0x0, (byte) 0x14, + (byte) 0x0, (byte) 0x8, (byte) 0x8, (byte) 0x8, (byte) 0x0, + (byte) 0x6d, (byte) 0x73, (byte) 0x3a, (byte) 0x54, (byte) 0x0, + (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x2, (byte) 0x0, + (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, + (byte) 0x0, (byte) 0x9, (byte) 0x0, (byte) 0x4, (byte) 0x0, + (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, + (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, + (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x4d, + (byte) 0x45, (byte) 0x54, (byte) 0x41, (byte) 0x2d, (byte) 0x49, + (byte) 0x4e, (byte) 0x46, (byte) 0x2f, (byte) 0xfe, (byte) 0xca, + (byte) 0x0, (byte) 0x0, (byte) 0x50, (byte) 0x4b, (byte) 0x1, + (byte) 0x2, (byte) 0x14, (byte) 0x0, (byte) 0x14, (byte) 0x0, + (byte) 0x8, (byte) 0x8, (byte) 0x8, (byte) 0x0, (byte) 0x6d, + (byte) 0x73, (byte) 0x3a, (byte) 0x54, (byte) 0xf4, (byte) 0x59, + (byte) 0xdc, (byte) 0xa6, (byte) 0x42, (byte) 0x0, (byte) 0x0, + (byte) 0x0, (byte) 0x42, (byte) 0x0, (byte) 0x0, (byte) 0x0, + (byte) 0x14, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, + (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, + (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x3d, + (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x4d, (byte) 0x45, + (byte) 0x54, (byte) 0x41, (byte) 0x2d, (byte) 0x49, (byte) 0x4e, + (byte) 0x46, (byte) 0x2f, (byte) 0x4d, (byte) 0x41, (byte) 0x4e, + (byte) 0x49, (byte) 0x46, (byte) 0x45, (byte) 0x53, (byte) 0x54, + (byte) 0x2e, (byte) 0x4d, (byte) 0x46, (byte) 0x50, (byte) 0x4b, + (byte) 0x1, (byte) 0x2, (byte) 0x14, (byte) 0x0, (byte) 0x14, + (byte) 0x0, (byte) 0x8, (byte) 0x8, (byte) 0x8, (byte) 0x0, + (byte) 0x6c, (byte) 0xb1, (byte) 0x38, (byte) 0x3e, (byte) 0x5a, + (byte) 0xf1, (byte) 0x0, (byte) 0x98, (byte) 0xdd, (byte) 0x0, + (byte) 0x0, (byte) 0x0, (byte) 0x67, (byte) 0x1, (byte) 0x0, + (byte) 0x0, (byte) 0x1c, (byte) 0x0, (byte) 0x0, (byte) 0x0, + (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, + (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, + (byte) 0xc1, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x6a, + (byte) 0x61, (byte) 0x76, (byte) 0x61, (byte) 0x78, (byte) 0x2f, + (byte) 0x69, (byte) 0x6e, (byte) 0x6a, (byte) 0x65, (byte) 0x63, + // We will modify 0x53, "S" within the CEN filename entry + (byte) 0x74, (byte) 0x2f, (byte) 0x53, (byte) 0x69, (byte) 0x6e, + (byte) 0x67, (byte) 0x6c, (byte) 0x65, (byte) 0x74, (byte) 0x6f, + (byte) 0x6e, (byte) 0x2e, (byte) 0x63, (byte) 0x6c, (byte) 0x61, + (byte) 0x73, (byte) 0x73, (byte) 0x50, (byte) 0x4b, (byte) 0x5, + (byte) 0x6, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, + (byte) 0x3, (byte) 0x0, (byte) 0x3, (byte) 0x0, (byte) 0xc7, + (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0xe8, (byte) 0x1, + (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, + }; + + /** + * Byte array representing a valid signed jar file prior modifying a filename + * in the CEN. + * The "Valid-EntryName.jar" jar file was signed via: + *
+     *     {@code
+     *        keytool -genkey -keyalg RSA -alias myFirstKey -keystore myKeystore -storepass changeit -keypass changeit
+     *        jarsigner -keystore myKeystore -verbose Valid-EntryName.jar -signedjar Signed-Valid-EntryName.jar myFirstKey
+     *      }
+     * 
+ * The ByteArray was created by: + *
+     *  {@code
+     *     var signedJar = Files.readAllBytes("Signed-Valid-EntryName.jar");
+     *     var signedValidEntryName = createByteArray(fooJar, "SIGNED_VALID_ENTRY_NAME");
+     *  }
+     * 
+ */ + public static byte[] SIGNED_VALID_ENTRY_NAME = { + (byte) 0x50, (byte) 0x4b, (byte) 0x3, (byte) 0x4, (byte) 0x14, + (byte) 0x0, (byte) 0x8, (byte) 0x8, (byte) 0x8, (byte) 0x0, + (byte) 0x17, (byte) 0x71, (byte) 0x3b, (byte) 0x54, (byte) 0x0, + (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, + (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, + (byte) 0x0, (byte) 0x14, (byte) 0x0, (byte) 0x0, (byte) 0x0, + (byte) 0x4d, (byte) 0x45, (byte) 0x54, (byte) 0x41, (byte) 0x2d, + (byte) 0x49, (byte) 0x4e, (byte) 0x46, (byte) 0x2f, (byte) 0x4d, + (byte) 0x41, (byte) 0x4e, (byte) 0x49, (byte) 0x46, (byte) 0x45, + (byte) 0x53, (byte) 0x54, (byte) 0x2e, (byte) 0x4d, (byte) 0x46, + (byte) 0x15, (byte) 0xcd, (byte) 0xbb, (byte) 0xe, (byte) 0x82, + (byte) 0x30, (byte) 0x18, (byte) 0x40, (byte) 0xe1, (byte) 0x9d, + (byte) 0x84, (byte) 0x77, (byte) 0xe8, (byte) 0xa8, (byte) 0x43, + (byte) 0xb, (byte) 0x28, (byte) 0x10, (byte) 0x42, (byte) 0xe2, + (byte) 0xc0, (byte) 0x45, (byte) 0xc1, (byte) 0x41, (byte) 0x31, + (byte) 0x21, (byte) 0x3a, (byte) 0xb8, (byte) 0x95, (byte) 0xfa, + (byte) 0xb, (byte) 0xad, (byte) 0xd8, (byte) 0x6a, (byte) 0xa9, + (byte) 0x17, (byte) 0xde, (byte) 0x5e, (byte) 0x5c, (byte) 0x4f, + (byte) 0x4e, (byte) 0xf2, (byte) 0xed, (byte) 0xa8, (byte) 0xe4, + (byte) 0x57, (byte) 0x18, (byte) 0xc, (byte) 0x3e, (byte) 0x81, + (byte) 0x1e, (byte) 0xb8, (byte) 0x92, (byte) 0x31, (byte) 0xf2, + (byte) 0x88, (byte) 0x6b, (byte) 0x5b, (byte) 0x99, (byte) 0x6, + (byte) 0x6a, (byte) 0xe0, (byte) 0x82, (byte) 0xd3, (byte) 0x71, + (byte) 0xa, (byte) 0x3e, (byte) 0x71, (byte) 0x89, (byte) 0x87, + (byte) 0x66, (byte) 0x95, (byte) 0xa6, (byte) 0xac, (byte) 0x7, + (byte) 0x94, (byte) 0x29, (byte) 0xfd, (byte) 0x50, (byte) 0x9a, + (byte) 0x9a, (byte) 0x69, (byte) 0x9e, (byte) 0xdb, (byte) 0x96, + (byte) 0x6d, (byte) 0xed, (byte) 0xe9, (byte) 0x1d, (byte) 0x62, + (byte) 0x24, (byte) 0xe8, (byte) 0x9b, (byte) 0x7e, (byte) 0x1d, + (byte) 0x2e, (byte) 0x5, (byte) 0x30, (byte) 0xe3, (byte) 0xd4, + (byte) 0x5c, (byte) 0xb6, (byte) 0x3d, (byte) 0x18, (byte) 0x25, + (byte) 0x9, (byte) 0xeb, (byte) 0xe9, (byte) 0x30, (byte) 0xd8, + (byte) 0x56, (byte) 0x5d, (byte) 0x26, (byte) 0x78, (byte) 0x11, + (byte) 0x84, (byte) 0x38, (byte) 0xe7, (byte) 0xed, (byte) 0x64, + (byte) 0xc5, (byte) 0x48, (byte) 0xb9, (byte) 0x7, (byte) 0xf0, + (byte) 0x97, (byte) 0x51, (byte) 0x1d, (byte) 0xe8, (byte) 0xcd, + (byte) 0xb3, (byte) 0x39, (byte) 0x46, (byte) 0x1f, (byte) 0x91, + (byte) 0xa4, (byte) 0x41, (byte) 0xb3, (byte) 0xbe, (byte) 0xf1, + (byte) 0x17, (byte) 0x1b, (byte) 0x4b, (byte) 0xd1, (byte) 0x55, + (byte) 0x45, (byte) 0x27, (byte) 0xf3, (byte) 0x73, (byte) 0xd1, + (byte) 0x9, (byte) 0x8, (byte) 0xc3, (byte) 0xed, (byte) 0xea, + (byte) 0x6f, (byte) 0xfc, (byte) 0x0, (byte) 0x50, (byte) 0x4b, + (byte) 0x7, (byte) 0x8, (byte) 0xc1, (byte) 0xfa, (byte) 0x9d, + (byte) 0xe2, (byte) 0x9e, (byte) 0x0, (byte) 0x0, (byte) 0x0, + (byte) 0xa6, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x50, + (byte) 0x4b, (byte) 0x3, (byte) 0x4, (byte) 0x14, (byte) 0x0, + (byte) 0x8, (byte) 0x8, (byte) 0x8, (byte) 0x0, (byte) 0x17, + (byte) 0x71, (byte) 0x3b, (byte) 0x54, (byte) 0x0, (byte) 0x0, + (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, + (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, + (byte) 0x14, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x4d, + (byte) 0x45, (byte) 0x54, (byte) 0x41, (byte) 0x2d, (byte) 0x49, + (byte) 0x4e, (byte) 0x46, (byte) 0x2f, (byte) 0x4d, (byte) 0x59, + (byte) 0x46, (byte) 0x49, (byte) 0x52, (byte) 0x53, (byte) 0x54, + (byte) 0x4b, (byte) 0x2e, (byte) 0x53, (byte) 0x46, (byte) 0x75, + (byte) 0x8d, (byte) 0xcb, (byte) 0x6e, (byte) 0x82, (byte) 0x40, + (byte) 0x18, (byte) 0x46, (byte) 0xf7, (byte) 0x24, (byte) 0xbc, + (byte) 0xc3, (byte) 0x2c, (byte) 0xdb, (byte) 0x10, (byte) 0xee, + (byte) 0xa8, (byte) 0x29, (byte) 0x49, (byte) 0x17, (byte) 0x23, + (byte) 0x2a, (byte) 0x4a, (byte) 0x41, (byte) 0xdb, (byte) 0x62, + (byte) 0x6d, (byte) 0xc2, (byte) 0x6e, (byte) 0x3a, (byte) 0x8c, + (byte) 0x64, (byte) 0x44, (byte) 0x67, (byte) 0xe8, (byte) 0xcc, + (byte) 0x2f, (byte) 0x5e, (byte) 0x9e, (byte) 0xbe, (byte) 0xa4, + (byte) 0xcb, (byte) 0x26, (byte) 0xdd, (byte) 0x9d, (byte) 0x7c, + (byte) 0xf9, (byte) 0x72, (byte) 0x4e, (byte) 0xc9, (byte) 0x1b, + (byte) 0x41, (byte) 0xe0, (byte) 0xac, (byte) 0x98, (byte) 0xbd, + (byte) 0x63, (byte) 0x4a, (byte) 0x73, (byte) 0x29, (byte) 0x62, + (byte) 0xe4, (byte) 0x3b, (byte) 0x9e, (byte) 0x69, (byte) 0x24, + (byte) 0x8a, (byte) 0x11, (byte) 0x60, (byte) 0xb5, (byte) 0x3d, + (byte) 0xbd, (byte) 0xd, (byte) 0x43, (byte) 0xe4, (byte) 0x78, + (byte) 0x8e, (byte) 0x8f, (byte) 0x1e, (byte) 0x36, (byte) 0x8a, + (byte) 0xd0, (byte) 0x23, (byte) 0x43, (byte) 0x89, (byte) 0x54, + (byte) 0x9d, (byte) 0x54, (byte) 0x4, (byte) 0x86, (byte) 0xf3, + (byte) 0xa3, (byte) 0x69, (byte) 0x94, (byte) 0x4b, (byte) 0x6c, + (byte) 0x7, (byte) 0xa3, (byte) 0xb1, (byte) 0x3d, (byte) 0xe3, + (byte) 0xd, (byte) 0xd3, (byte) 0x60, (byte) 0x17, (byte) 0x44, + (byte) 0xf0, (byte) 0xfd, (byte) 0x0, (byte) 0x31, (byte) 0xda, + (byte) 0xeb, (byte) 0xd9, (byte) 0xc6, (byte) 0xad, (byte) 0x2c, + (byte) 0xab, (byte) 0x29, (byte) 0xb2, (byte) 0x57, (byte) 0xbc, + (byte) 0xfb, (byte) 0x8, (byte) 0x57, (byte) 0xa3, (byte) 0x2e, + (byte) 0x97, (byte) 0x3d, (byte) 0xe0, (byte) 0x4d, (byte) 0x48, + (byte) 0xb3, (byte) 0xa0, (byte) 0x4d, (byte) 0x73, (byte) 0xd7, + (byte) 0xf3, (byte) 0x83, (byte) 0xa0, (byte) 0xbf, (byte) 0x15, + (byte) 0x8b, (byte) 0xba, (byte) 0x78, (byte) 0xfe, (byte) 0x57, + (byte) 0x33, (byte) 0x0, (byte) 0x17, (byte) 0x36, (byte) 0x6, + (byte) 0x50, (byte) 0xfc, (byte) 0xeb, (byte) 0xc, (byte) 0x4c, + (byte) 0xc7, (byte) 0x28, (byte) 0xa4, (byte) 0x55, (byte) 0xb6, + (byte) 0x8e, (byte) 0x40, (byte) 0x94, (byte) 0xf7, (byte) 0x76, + (byte) 0x4b, (byte) 0xd2, (byte) 0xc8, (byte) 0x67, (byte) 0xb, + (byte) 0xa8, (byte) 0x93, (byte) 0xc9, (byte) 0x64, (byte) 0x3a, + (byte) 0x29, (byte) 0x96, (byte) 0xe3, (byte) 0xd6, (byte) 0x6a, + (byte) 0x4d, (byte) 0x3, (byte) 0x9d, (byte) 0xe7, (byte) 0xdd, + (byte) 0xf5, (byte) 0x6e, (byte) 0x61, (byte) 0x39, (byte) 0xbf, + (byte) 0xd6, (byte) 0x74, (byte) 0x30, (byte) 0x9b, (byte) 0xc6, + (byte) 0x9a, (byte) 0x9c, (byte) 0x58, (byte) 0x8c, (byte) 0xe, + (byte) 0xa4, (byte) 0x27, (byte) 0x57, (byte) 0x97, (byte) 0x8b, + (byte) 0x3, (byte) 0xa3, (byte) 0xe0, (byte) 0x96, (byte) 0x5c, + (byte) 0x34, (byte) 0x47, (byte) 0x6, (byte) 0x52, (byte) 0x38, + (byte) 0xf4, (byte) 0x48, (byte) 0xb4, (byte) 0xfe, (byte) 0xdb, + (byte) 0x8f, (byte) 0xd1, (byte) 0x28, (byte) 0xf4, (byte) 0xab, + (byte) 0xd5, (byte) 0xc9, (byte) 0xc5, (byte) 0x51, (byte) 0xe2, + (byte) 0xdf, (byte) 0x29, (byte) 0x93, (byte) 0x5b, (byte) 0xac, + (byte) 0x32, (byte) 0xef, (byte) 0xe9, (byte) 0x70, (byte) 0xc9, + (byte) 0xd3, (byte) 0xf7, (byte) 0x6f, (byte) 0xae, (byte) 0x39, + (byte) 0x81, (byte) 0xf4, (byte) 0xd, (byte) 0x7f, (byte) 0x36, + (byte) 0x51, (byte) 0xc7, (byte) 0x9b, (byte) 0x17, (byte) 0xef, + (byte) 0xb7, (byte) 0xf1, (byte) 0x3, (byte) 0x50, (byte) 0x4b, + (byte) 0x7, (byte) 0x8, (byte) 0x8b, (byte) 0xcb, (byte) 0xd5, + (byte) 0xea, (byte) 0x3, (byte) 0x1, (byte) 0x0, (byte) 0x0, + (byte) 0x48, (byte) 0x1, (byte) 0x0, (byte) 0x0, (byte) 0x50, + (byte) 0x4b, (byte) 0x3, (byte) 0x4, (byte) 0x14, (byte) 0x0, + (byte) 0x8, (byte) 0x8, (byte) 0x8, (byte) 0x0, (byte) 0x17, + (byte) 0x71, (byte) 0x3b, (byte) 0x54, (byte) 0x0, (byte) 0x0, + (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, + (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, + (byte) 0x15, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x4d, + (byte) 0x45, (byte) 0x54, (byte) 0x41, (byte) 0x2d, (byte) 0x49, + (byte) 0x4e, (byte) 0x46, (byte) 0x2f, (byte) 0x4d, (byte) 0x59, + (byte) 0x46, (byte) 0x49, (byte) 0x52, (byte) 0x53, (byte) 0x54, + (byte) 0x4b, (byte) 0x2e, (byte) 0x52, (byte) 0x53, (byte) 0x41, + (byte) 0x33, (byte) 0x68, (byte) 0x62, (byte) 0xd, (byte) 0x61, + (byte) 0xe3, (byte) 0xd4, (byte) 0x6a, (byte) 0xf3, (byte) 0x68, + (byte) 0xfb, (byte) 0xce, (byte) 0xcb, (byte) 0xc8, (byte) 0xce, + (byte) 0xb4, (byte) 0xa0, (byte) 0x89, (byte) 0xd5, (byte) 0xd5, + (byte) 0xa0, (byte) 0x89, (byte) 0xd5, (byte) 0x91, (byte) 0x89, + (byte) 0x91, (byte) 0xd1, (byte) 0x90, (byte) 0xdf, (byte) 0x80, + (byte) 0x97, (byte) 0x8d, (byte) 0x33, (byte) 0xa1, (byte) 0xcd, + (byte) 0x83, (byte) 0x31, (byte) 0x95, (byte) 0x99, (byte) 0x85, + (byte) 0x89, (byte) 0x91, (byte) 0x95, (byte) 0xc1, (byte) 0x80, + (byte) 0x1b, (byte) 0xa1, (byte) 0x90, (byte) 0x71, (byte) 0x41, + (byte) 0x13, (byte) 0x73, (byte) 0x85, (byte) 0x41, (byte) 0x13, + (byte) 0x73, (byte) 0x89, (byte) 0x41, (byte) 0x13, (byte) 0x53, + (byte) 0xcc, (byte) 0x2, (byte) 0x66, (byte) 0x26, (byte) 0x46, + (byte) 0x26, (byte) 0x26, (byte) 0x4e, (byte) 0x86, (byte) 0xcd, + (byte) 0xbc, (byte) 0x81, (byte) 0x6c, (byte) 0xf9, (byte) 0x5b, + (byte) 0xf6, (byte) 0xaa, (byte) 0x82, (byte) 0xf4, (byte) 0x41, + (byte) 0x15, (byte) 0x32, (byte) 0x72, (byte) 0x3, (byte) 0xf5, + (byte) 0x65, (byte) 0x18, (byte) 0x72, (byte) 0x1b, (byte) 0x70, + (byte) 0xb2, (byte) 0x31, (byte) 0x87, (byte) 0xb2, (byte) 0xb0, + (byte) 0x9, (byte) 0x33, (byte) 0x85, (byte) 0x6, (byte) 0xc3, + (byte) 0x38, (byte) 0x1c, (byte) 0xc2, (byte) 0x4c, (byte) 0xbe, + (byte) 0x8e, (byte) 0x86, (byte) 0xc2, (byte) 0x6, (byte) 0x82, + (byte) 0x20, (byte) 0xe, (byte) 0xbb, (byte) 0x30, (byte) 0x97, + (byte) 0x53, (byte) 0x7e, (byte) 0x45, (byte) 0x52, (byte) 0x7e, + (byte) 0x51, (byte) 0x7e, (byte) 0x69, (byte) 0x7a, (byte) 0x6, + (byte) 0xd8, (byte) 0x66, (byte) 0xa0, (byte) 0x20, (byte) 0x97, + (byte) 0x30, (byte) 0x9b, (byte) 0x7f, (byte) 0x51, (byte) 0x62, + (byte) 0x72, (byte) 0x4e, (byte) 0xaa, (byte) 0x21, (byte) 0x2f, + (byte) 0xd0, (byte) 0x6e, (byte) 0xa0, (byte) 0x0, (byte) 0xb7, + (byte) 0x30, (byte) 0x8b, (byte) 0x57, (byte) 0x62, (byte) 0x59, + (byte) 0xa2, (byte) 0xa1, (byte) 0xb8, (byte) 0x81, (byte) 0x28, + (byte) 0x88, (byte) 0xcb, (byte) 0x2c, (byte) 0xcc, (byte) 0xe7, + (byte) 0x93, (byte) 0x98, (byte) 0x97, (byte) 0x9c, (byte) 0xaa, + (byte) 0xe0, (byte) 0x98, (byte) 0x97, (byte) 0x92, (byte) 0x5a, + (byte) 0x54, (byte) 0x9c, (byte) 0x9a, (byte) 0x67, (byte) 0x20, + (byte) 0x27, (byte) 0xce, (byte) 0x6b, (byte) 0x64, (byte) 0x64, + (byte) 0x60, (byte) 0x68, (byte) 0x64, (byte) 0x6e, (byte) 0x68, + (byte) 0x69, (byte) 0x60, (byte) 0x6a, (byte) 0x60, (byte) 0x19, + (byte) 0x5, (byte) 0xe6, (byte) 0x9a, (byte) 0xc0, (byte) 0xb9, + (byte) 0x74, (byte) 0x74, (byte) 0x49, (byte) 0x13, (byte) 0xa3, + (byte) 0x12, (byte) 0x72, (byte) 0x30, (byte) 0x0, (byte) 0x83, + (byte) 0x8f, (byte) 0xb9, (byte) 0x89, (byte) 0x91, (byte) 0x9f, + (byte) 0x1, (byte) 0x28, (byte) 0xce, (byte) 0xc5, (byte) 0xd4, + (byte) 0xc4, (byte) 0xc8, (byte) 0xc8, (byte) 0x30, (byte) 0xd7, + (byte) 0xef, (byte) 0xf5, (byte) 0x1c, (byte) 0x99, (byte) 0x95, + (byte) 0xf7, (byte) 0xca, (byte) 0x4e, (byte) 0xff, (byte) 0x75, + (byte) 0x49, (byte) 0xe4, (byte) 0xa9, (byte) 0x8e, (byte) 0xb8, + (byte) 0x91, (byte) 0xe1, (byte) 0xb5, (byte) 0xf3, (byte) 0xca, + (byte) 0xc1, (byte) 0xe9, (byte) 0x6e, (byte) 0xcd, (byte) 0x97, + (byte) 0xef, (byte) 0x28, (byte) 0x25, (byte) 0xc7, (byte) 0x89, + (byte) 0x6d, (byte) 0xf2, (byte) 0xb, (byte) 0x10, (byte) 0xf0, + (byte) 0x7f, (byte) 0x63, (byte) 0xb8, (byte) 0x91, (byte) 0xfb, + (byte) 0xff, (byte) 0x6b, (byte) 0xfd, (byte) 0x85, (byte) 0x17, + (byte) 0x96, (byte) 0x67, (byte) 0x79, (byte) 0xfd, (byte) 0xa8, + (byte) 0x7b, (byte) 0xbf, (byte) 0x75, (byte) 0xad, (byte) 0x77, + (byte) 0xc0, (byte) 0x4e, (byte) 0x9f, (byte) 0xb6, (byte) 0x9e, + (byte) 0xee, (byte) 0xd, (byte) 0xcb, (byte) 0xf8, (byte) 0xd7, + (byte) 0xc9, (byte) 0xdc, (byte) 0x2c, (byte) 0xee, (byte) 0x4d, + (byte) 0x91, (byte) 0x2e, (byte) 0xb0, (byte) 0x48, (byte) 0xd8, + (byte) 0xb2, (byte) 0x63, (byte) 0xcb, (byte) 0x91, (byte) 0x8f, + (byte) 0x89, (byte) 0x69, (byte) 0x7a, (byte) 0x53, (byte) 0x6f, + (byte) 0x6d, (byte) 0x59, (byte) 0xa3, (byte) 0xd3, (byte) 0xfb, + (byte) 0xab, (byte) 0xa0, (byte) 0xe6, (byte) 0xab, (byte) 0x24, + (byte) 0x73, (byte) 0xd0, (byte) 0x32, (byte) 0xc6, (byte) 0x2c, + (byte) 0x1, (byte) 0x29, (byte) 0xf5, (byte) 0xa3, (byte) 0x1a, + (byte) 0x62, (byte) 0xc5, (byte) 0x4f, (byte) 0xce, (byte) 0xda, + (byte) 0xed, (byte) 0x54, (byte) 0x8b, (byte) 0xfb, (byte) 0x26, + (byte) 0x1b, (byte) 0xba, (byte) 0xe0, (byte) 0xb1, (byte) 0x76, + (byte) 0xb9, (byte) 0x75, (byte) 0xcb, (byte) 0x67, (byte) 0x27, + (byte) 0xa6, (byte) 0xd2, (byte) 0xdb, (byte) 0xb9, (byte) 0x7, + (byte) 0x5, (byte) 0x3e, (byte) 0xee, (byte) 0x9c, (byte) 0x64, + (byte) 0x74, (byte) 0xdc, (byte) 0xad, (byte) 0x80, (byte) 0x8d, + (byte) 0xeb, (byte) 0xe5, (byte) 0xb3, (byte) 0x15, (byte) 0x9b, + (byte) 0x33, (byte) 0xf, (byte) 0x1f, (byte) 0xf7, (byte) 0x34, + (byte) 0x9a, (byte) 0xf5, (byte) 0xf2, (byte) 0xc3, (byte) 0x14, + (byte) 0xd3, (byte) 0x48, (byte) 0x11, (byte) 0xa1, (byte) 0xea, + (byte) 0xe7, (byte) 0xea, (byte) 0x95, (byte) 0x95, (byte) 0x32, + (byte) 0x37, (byte) 0x15, (byte) 0xfa, (byte) 0x2, (byte) 0xfe, + (byte) 0xbd, (byte) 0x61, (byte) 0x17, (byte) 0xb2, (byte) 0xcc, + (byte) 0x9c, (byte) 0xf3, (byte) 0x6e, (byte) 0x9a, (byte) 0x57, + (byte) 0xce, (byte) 0x54, (byte) 0x55, (byte) 0x33, (byte) 0x96, + (byte) 0x64, (byte) 0xde, (byte) 0x2b, (byte) 0x6b, (byte) 0x39, + (byte) 0xfe, (byte) 0x76, (byte) 0xe7, (byte) 0xdc, (byte) 0xb2, + (byte) 0xb3, (byte) 0xbe, (byte) 0xed, (byte) 0x52, (byte) 0x7b, + (byte) 0xb9, (byte) 0x90, (byte) 0xd9, (byte) 0x85, (byte) 0xd9, + (byte) 0xed, (byte) 0xbb, (byte) 0x57, (byte) 0x35, (byte) 0xcf, + (byte) 0xe6, (byte) 0x87, (byte) 0xf3, (byte) 0x4f, (byte) 0x4, + (byte) 0x54, (byte) 0x7b, (byte) 0x95, (byte) 0x5c, (byte) 0xd0, + (byte) 0x9d, (byte) 0x7a, (byte) 0xbd, (byte) 0xb7, (byte) 0x6f, + (byte) 0xe9, (byte) 0x6f, (byte) 0x8f, (byte) 0x86, (byte) 0x93, + (byte) 0x5b, (byte) 0x97, (byte) 0xec, (byte) 0xfe, (byte) 0xd5, + (byte) 0x78, (byte) 0xc2, (byte) 0xd6, (byte) 0xa7, (byte) 0x46, + (byte) 0x8d, (byte) 0x89, (byte) 0xb9, (byte) 0x57, (byte) 0xab, + (byte) 0xb5, (byte) 0x75, (byte) 0xab, (byte) 0xcd, (byte) 0x9d, + (byte) 0x43, (byte) 0x9c, (byte) 0xde, (byte) 0x17, (byte) 0x2b, + (byte) 0x3e, (byte) 0xfa, (byte) 0xbb, (byte) 0x4c, (byte) 0x96, + (byte) 0x9c, (byte) 0x73, (byte) 0xe3, (byte) 0x64, (byte) 0xb4, + (byte) 0xcc, (byte) 0xcb, (byte) 0xfd, (byte) 0x4c, (byte) 0xcc, + (byte) 0x8c, (byte) 0xc, (byte) 0x8c, (byte) 0x8b, (byte) 0x15, + (byte) 0xd, (byte) 0xe4, (byte) 0xd, (byte) 0x64, (byte) 0x81, + (byte) 0x1, (byte) 0x28, (byte) 0xcb, (byte) 0xc7, (byte) 0x22, + (byte) 0xc6, (byte) 0x22, (byte) 0xf2, (byte) 0xb0, (byte) 0xe4, + (byte) 0x67, (byte) 0x69, (byte) 0xfa, (byte) 0xd5, (byte) 0x12, + (byte) 0xdf, (byte) 0x8c, (byte) 0xdf, (byte) 0x21, (byte) 0xd5, + (byte) 0x9f, (byte) 0x17, (byte) 0x8b, (byte) 0xfa, (byte) 0x68, + (byte) 0x9, (byte) 0xf1, (byte) 0xcb, (byte) 0xa0, (byte) 0xa5, + (byte) 0x25, (byte) 0x66, (byte) 0x50, (byte) 0xd8, (byte) 0xf5, + (byte) 0x73, (byte) 0xfc, (byte) 0xf9, (byte) 0xaf, (byte) 0x12, + (byte) 0xbf, (byte) 0x42, (byte) 0xbb, (byte) 0x41, (byte) 0xe0, + (byte) 0xb6, (byte) 0x91, (byte) 0xfc, (byte) 0xbc, (byte) 0xe3, + (byte) 0xf3, (byte) 0x39, (byte) 0x1c, (byte) 0x1b, (byte) 0xf3, + (byte) 0xd8, (byte) 0x2f, (byte) 0x7c, (byte) 0xe9, (byte) 0x7b, + (byte) 0xd2, (byte) 0x1a, (byte) 0xf0, (byte) 0xb3, (byte) 0x52, + (byte) 0x61, (byte) 0xb5, (byte) 0xbf, (byte) 0xde, (byte) 0x31, + (byte) 0xf6, (byte) 0x17, (byte) 0xe7, (byte) 0x5a, (byte) 0x9b, + (byte) 0x9f, (byte) 0x6f, (byte) 0xf5, (byte) 0x94, (byte) 0x4b, + (byte) 0x6d, (byte) 0x31, (byte) 0x2e, (byte) 0x56, (byte) 0x37, + (byte) 0x5c, (byte) 0x64, (byte) 0x32, (byte) 0xc1, (byte) 0xef, + (byte) 0x75, (byte) 0xcf, (byte) 0xe9, (byte) 0x8c, (byte) 0xcc, + (byte) 0xcf, (byte) 0x9d, (byte) 0xdf, (byte) 0x34, (byte) 0x1b, + (byte) 0xf4, (byte) 0xe4, (byte) 0x75, (byte) 0xac, (byte) 0xff, + (byte) 0xbf, (byte) 0x5b, (byte) 0xaf, (byte) 0xfa, (byte) 0x98, + (byte) 0x5f, (byte) 0x22, (byte) 0x75, (byte) 0xf5, (byte) 0xd5, + (byte) 0x8c, (byte) 0xd3, (byte) 0xae, (byte) 0x17, (byte) 0xab, + (byte) 0xad, (byte) 0xb9, (byte) 0x6a, (byte) 0x17, (byte) 0x84, + (byte) 0xf8, (byte) 0xf9, (byte) 0x72, (byte) 0xf5, (byte) 0x7b, + (byte) 0xad, (byte) 0x5b, (byte) 0xd3, (byte) 0xd0, (byte) 0x5f, + (byte) 0x71, (byte) 0x29, (byte) 0xa0, (byte) 0xa3, (byte) 0x2c, + (byte) 0xfc, (byte) 0x73, (byte) 0xc2, (byte) 0x3f, (byte) 0xd6, + (byte) 0xf4, (byte) 0x9c, (byte) 0xbe, (byte) 0xa9, (byte) 0x2c, + (byte) 0xf5, (byte) 0x7e, (byte) 0x17, (byte) 0xdf, (byte) 0x95, + (byte) 0xb2, (byte) 0xdd, (byte) 0x29, (byte) 0x33, (byte) 0xb8, + (byte) 0x66, (byte) 0x56, (byte) 0x55, (byte) 0xcc, (byte) 0xba, + (byte) 0x6a, (byte) 0x5d, (byte) 0x92, (byte) 0xeb, (byte) 0xe7, + (byte) 0x7e, (byte) 0x2f, (byte) 0x67, (byte) 0x99, (byte) 0xa2, + (byte) 0xb, (byte) 0xda, (byte) 0x7d, (byte) 0xa7, (byte) 0x73, + (byte) 0x2b, (byte) 0xb6, (byte) 0x5f, (byte) 0x7e, (byte) 0x3b, + (byte) 0x45, (byte) 0xce, (byte) 0xdc, (byte) 0x28, (byte) 0xed, + (byte) 0xed, (byte) 0xf2, (byte) 0x84, (byte) 0xf0, (byte) 0xc2, + (byte) 0x8d, (byte) 0x62, (byte) 0xbc, (byte) 0xe, (byte) 0xac, + (byte) 0x29, (byte) 0x33, (byte) 0xe3, (byte) 0xdd, (byte) 0xb6, + (byte) 0x33, (byte) 0x98, (byte) 0x15, (byte) 0x54, (byte) 0x4f, + (byte) 0x6f, (byte) 0x8d, (byte) 0xba, (byte) 0x11, (byte) 0xf9, + (byte) 0xeb, (byte) 0xd1, (byte) 0x7e, (byte) 0x3, (byte) 0x13, + (byte) 0xd6, (byte) 0xf6, (byte) 0xea, (byte) 0xee, (byte) 0xc8, + (byte) 0xa5, (byte) 0x7c, (byte) 0xf, (byte) 0x14, (byte) 0x1d, + (byte) 0xae, (byte) 0xfc, (byte) 0xb4, (byte) 0xfb, (byte) 0x2a, + (byte) 0xa4, (byte) 0xf7, (byte) 0xd0, (byte) 0x7b, (byte) 0x53, + (byte) 0x73, (byte) 0xc6, (byte) 0x8b, (byte) 0x6d, (byte) 0xc7, + (byte) 0xac, (byte) 0x8f, (byte) 0x68, (byte) 0x5e, (byte) 0x95, + (byte) 0x7a, (byte) 0x34, (byte) 0xd7, (byte) 0x4e, (byte) 0x5b, + (byte) 0x35, (byte) 0xd3, (byte) 0xe1, (byte) 0xe3, (byte) 0xd7, + (byte) 0x94, (byte) 0x60, (byte) 0xd3, (byte) 0xa4, (byte) 0x93, + (byte) 0x7a, (byte) 0x86, (byte) 0x3f, (byte) 0x35, (byte) 0x58, + (byte) 0x1e, (byte) 0x88, (byte) 0x5d, (byte) 0x7e, (byte) 0xd0, + (byte) 0xf6, (byte) 0x63, (byte) 0xf3, (byte) 0xe3, (byte) 0xd4, + (byte) 0xf, (byte) 0x3b, (byte) 0xd5, (byte) 0xaf, (byte) 0x98, + (byte) 0xfc, (byte) 0x6c, (byte) 0x3e, (byte) 0x66, (byte) 0x1e, + (byte) 0xe5, (byte) 0xe6, (byte) 0x60, (byte) 0x55, (byte) 0x7e, + (byte) 0x78, (byte) 0x45, (byte) 0x89, (byte) 0x86, (byte) 0xde, + (byte) 0xc6, (byte) 0x4f, (byte) 0x86, (byte) 0x4d, (byte) 0x8c, + (byte) 0xb, (byte) 0x80, (byte) 0x9, (byte) 0x69, (byte) 0xe, + (byte) 0x30, (byte) 0x93, (byte) 0x1a, (byte) 0x94, (byte) 0xd2, + (byte) 0x2f, (byte) 0x4d, (byte) 0xa3, (byte) 0xe5, (byte) 0x70, + (byte) 0xe4, (byte) 0x92, (byte) 0x1, (byte) 0x35, (byte) 0xa5, + (byte) 0xb3, (byte) 0x34, (byte) 0x31, (byte) 0x32, (byte) 0xf4, + (byte) 0xa, (byte) 0x9c, (byte) 0xb0, (byte) 0x9d, (byte) 0x61, + (byte) 0x3e, (byte) 0x53, (byte) 0x78, (byte) 0xce, (byte) 0x42, + (byte) 0xb7, (byte) 0x7, (byte) 0x9b, (byte) 0xcb, (byte) 0x95, + (byte) 0xb6, (byte) 0x74, (byte) 0xe8, (byte) 0x16, (byte) 0x8, + (byte) 0xfe, (byte) 0x3c, (byte) 0x74, (byte) 0xe1, (byte) 0xe, + (byte) 0x87, (byte) 0xf6, (byte) 0x3a, (byte) 0xeb, (byte) 0x45, + (byte) 0xfb, (byte) 0x97, (byte) 0x71, (byte) 0xbf, (byte) 0xaa, + (byte) 0x13, (byte) 0x89, (byte) 0x78, (byte) 0x1e, (byte) 0x74, + (byte) 0xe4, (byte) 0x97, (byte) 0x69, (byte) 0xf2, (byte) 0xe5, + (byte) 0xd, (byte) 0x22, (byte) 0xa, (byte) 0x73, (byte) 0xf7, + (byte) 0x5e, (byte) 0xd1, (byte) 0x92, (byte) 0xdb, (byte) 0x25, + (byte) 0x72, (byte) 0xf0, (byte) 0xdb, (byte) 0x34, (byte) 0xc3, + (byte) 0x79, (byte) 0xcb, (byte) 0xaa, (byte) 0xcb, (byte) 0xc, + (byte) 0xd4, (byte) 0xd3, (byte) 0xd6, (byte) 0x9e, (byte) 0xb8, + (byte) 0xa9, (byte) 0xf3, (byte) 0x71, (byte) 0xa5, (byte) 0x48, + (byte) 0x4a, (byte) 0xe2, (byte) 0x57, (byte) 0xbb, (byte) 0xb6, + (byte) 0xe5, (byte) 0xaf, (byte) 0x5e, (byte) 0x4, (byte) 0x48, + (byte) 0xd6, (byte) 0xd5, (byte) 0x71, (byte) 0xc8, (byte) 0xaf, + (byte) 0x34, (byte) 0xe0, (byte) 0xae, (byte) 0x5e, (byte) 0x1a, + (byte) 0xbe, (byte) 0xb5, (byte) 0xc3, (byte) 0xbc, (byte) 0xa9, + (byte) 0xfc, (byte) 0x51, (byte) 0xc, (byte) 0x73, (byte) 0xef, + (byte) 0x83, (byte) 0x47, (byte) 0x3e, (byte) 0x72, (byte) 0x3b, + (byte) 0xce, (byte) 0xbe, (byte) 0xfd, (byte) 0xb4, (byte) 0x41, + (byte) 0x20, (byte) 0x54, (byte) 0xf2, (byte) 0x47, (byte) 0x45, + (byte) 0x69, (byte) 0xb8, (byte) 0xcd, (byte) 0x59, (byte) 0xbb, + (byte) 0x8e, (byte) 0xf2, (byte) 0xc3, (byte) 0x86, (byte) 0xea, + (byte) 0x32, (byte) 0x1f, (byte) 0xbf, (byte) 0x4, (byte) 0x6b, + (byte) 0xda, (byte) 0xaa, (byte) 0x2b, (byte) 0x33, (byte) 0x7d, + (byte) 0x54, (byte) 0xf2, (byte) 0x9, (byte) 0x16, (byte) 0x16, + (byte) 0xfa, (byte) 0x5b, (byte) 0xb6, (byte) 0x6d, (byte) 0x42, + (byte) 0xaa, (byte) 0x9e, (byte) 0x9e, (byte) 0x16, (byte) 0x73, + (byte) 0xc0, (byte) 0x6a, (byte) 0xf7, (byte) 0xbf, (byte) 0x13, + (byte) 0xf9, (byte) 0xbc, (byte) 0xfc, (byte) 0x79, (byte) 0xcc, + (byte) 0x84, (byte) 0x6a, (byte) 0x9f, (byte) 0x9c, (byte) 0x88, + (byte) 0xcd, (byte) 0xb3, (byte) 0xb3, (byte) 0x98, (byte) 0xc0, + (byte) 0xf3, (byte) 0xf0, (byte) 0xc4, (byte) 0x86, (byte) 0x6f, + (byte) 0x86, (byte) 0xd1, (byte) 0x97, (byte) 0x53, (byte) 0x4b, + (byte) 0x6b, (byte) 0xb9, (byte) 0xbe, (byte) 0xca, (byte) 0xde, + (byte) 0xd8, (byte) 0x23, (byte) 0x58, (byte) 0xee, (byte) 0x92, + (byte) 0xcc, (byte) 0x7f, (byte) 0xa7, (byte) 0xe7, (byte) 0xbc, + (byte) 0xff, (byte) 0x84, (byte) 0x93, (byte) 0x13, (byte) 0xcc, + (byte) 0x94, (byte) 0xe, (byte) 0x73, (byte) 0x9b, (byte) 0x2c, + (byte) 0x9d, (byte) 0xfa, (byte) 0x62, (byte) 0x75, (byte) 0x98, + (byte) 0x6f, (byte) 0x70, (byte) 0xf1, (byte) 0x97, (byte) 0xaa, + (byte) 0xe5, (byte) 0x9b, (byte) 0xa6, (byte) 0xac, (byte) 0x4e, + (byte) 0x7f, (byte) 0xbb, (byte) 0xc2, (byte) 0x34, (byte) 0xec, + (byte) 0xe2, (byte) 0xbe, (byte) 0xc0, (byte) 0x99, (byte) 0x1d, + (byte) 0x9f, (byte) 0xb8, (byte) 0xa5, (byte) 0x6b, (byte) 0xb8, + (byte) 0x4, (byte) 0xf7, (byte) 0x2d, (byte) 0x11, (byte) 0x9a, + (byte) 0x56, (byte) 0xb1, (byte) 0xa9, (byte) 0xbd, (byte) 0xb4, + (byte) 0x8f, (byte) 0x57, (byte) 0x60, (byte) 0xcf, (byte) 0xb3, + (byte) 0xab, (byte) 0xad, (byte) 0x86, (byte) 0xea, (byte) 0x46, + (byte) 0xbb, (byte) 0x7b, (byte) 0xf7, (byte) 0xfe, (byte) 0xe8, + (byte) 0xd6, (byte) 0xd2, (byte) 0x9d, (byte) 0x3, (byte) 0x0, + (byte) 0x50, (byte) 0x4b, (byte) 0x7, (byte) 0x8, (byte) 0xba, + (byte) 0x40, (byte) 0x24, (byte) 0x13, (byte) 0x4c, (byte) 0x4, + (byte) 0x0, (byte) 0x0, (byte) 0x58, (byte) 0x5, (byte) 0x0, + (byte) 0x0, (byte) 0x50, (byte) 0x4b, (byte) 0x3, (byte) 0x4, + (byte) 0x14, (byte) 0x0, (byte) 0x8, (byte) 0x8, (byte) 0x8, + (byte) 0x0, (byte) 0x6d, (byte) 0x73, (byte) 0x3a, (byte) 0x54, + (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, + (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, + (byte) 0x0, (byte) 0x0, (byte) 0x9, (byte) 0x0, (byte) 0x4, + (byte) 0x0, (byte) 0x4d, (byte) 0x45, (byte) 0x54, (byte) 0x41, + (byte) 0x2d, (byte) 0x49, (byte) 0x4e, (byte) 0x46, (byte) 0x2f, + (byte) 0xfe, (byte) 0xca, (byte) 0x0, (byte) 0x0, (byte) 0x3, + (byte) 0x0, (byte) 0x50, (byte) 0x4b, (byte) 0x7, (byte) 0x8, + (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x2, + (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, + (byte) 0x0, (byte) 0x0, (byte) 0x50, (byte) 0x4b, (byte) 0x3, + (byte) 0x4, (byte) 0x14, (byte) 0x0, (byte) 0x8, (byte) 0x8, + (byte) 0x8, (byte) 0x0, (byte) 0x6c, (byte) 0xb1, (byte) 0x38, + (byte) 0x3e, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, + (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, + (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x1c, (byte) 0x0, + (byte) 0x0, (byte) 0x0, (byte) 0x6a, (byte) 0x61, (byte) 0x76, + (byte) 0x61, (byte) 0x78, (byte) 0x2f, (byte) 0x69, (byte) 0x6e, + (byte) 0x6a, (byte) 0x65, (byte) 0x63, (byte) 0x74, (byte) 0x2f, + (byte) 0x53, (byte) 0x69, (byte) 0x6e, (byte) 0x67, (byte) 0x6c, + (byte) 0x65, (byte) 0x74, (byte) 0x6f, (byte) 0x6e, (byte) 0x2e, + (byte) 0x63, (byte) 0x6c, (byte) 0x61, (byte) 0x73, (byte) 0x73, + (byte) 0x85, (byte) 0x90, (byte) 0x4d, (byte) 0x4b, (byte) 0x82, + (byte) 0x41, (byte) 0x10, (byte) 0xc7, (byte) 0xff, (byte) 0xa3, + (byte) 0xd9, (byte) 0x63, (byte) 0x56, (byte) 0xe6, (byte) 0x21, + (byte) 0x5, (byte) 0x4f, (byte) 0xda, (byte) 0xc5, (byte) 0x63, + (byte) 0x4b, (byte) 0xe7, (byte) 0x4e, (byte) 0x41, (byte) 0x6, + (byte) 0x81, (byte) 0xa5, (byte) 0x3c, (byte) 0x5a, (byte) 0xf7, + (byte) 0x75, (byte) 0x1b, (byte) 0x64, (byte) 0x65, (byte) 0xdd, + (byte) 0x8d, (byte) 0xdc, (byte) 0x47, (byte) 0xea, (byte) 0xab, + (byte) 0x79, (byte) 0xe8, (byte) 0x3, (byte) 0xf4, (byte) 0xa1, + (byte) 0xc4, (byte) 0xd9, (byte) 0xe, (byte) 0x4a, (byte) 0x20, + (byte) 0x34, (byte) 0x30, (byte) 0x2f, (byte) 0xcc, (byte) 0xfc, + (byte) 0x66, (byte) 0x98, (byte) 0x99, (byte) 0x9f, (byte) 0xcd, + (byte) 0xfa, (byte) 0x1b, (byte) 0xc0, (byte) 0xd, (byte) 0x1a, + (byte) 0x84, (byte) 0x2c, (byte) 0x7f, (byte) 0x79, (byte) 0x9e, + (byte) 0x3c, (byte) 0x3e, (byte) 0xf5, (byte) 0x9, (byte) 0x8d, + (byte) 0xb9, (byte) 0x5e, (byte) 0x69, (byte) 0xe5, (byte) 0xb4, + (byte) 0x9f, (byte) 0xa9, (byte) 0xe1, (byte) 0x74, (byte) 0xce, + (byte) 0x26, (byte) 0x12, (byte) 0x3a, (byte) 0xfb, (byte) 0x94, + (byte) 0xf6, (byte) 0x3e, (byte) 0x44, (byte) 0x1d, (byte) 0x6d, + (byte) 0xf0, (byte) 0xea, (byte) 0x6e, (byte) 0x17, (byte) 0x12, + (byte) 0x5a, (byte) 0x89, (byte) 0xf8, (byte) 0x54, (byte) 0xd6, + (byte) 0xa7, (byte) 0x6, (byte) 0x35, (byte) 0xb6, (byte) 0x7e, + (byte) 0xe6, (byte) 0x38, (byte) 0xa6, (byte) 0x42, (byte) 0x65, + (byte) 0xa5, (byte) 0x5d, (byte) 0xc1, (byte) 0x19, (byte) 0x4a, + (byte) 0x19, (byte) 0xca, (byte) 0x19, (byte) 0x8e, (byte) 0x8, + (byte) 0x57, (byte) 0x83, (byte) 0x83, (byte) 0xc3, (byte) 0xee, + (byte) 0x83, (byte) 0x29, (byte) 0x16, (byte) 0xec, (byte) 0x23, + (byte) 0xbf, (byte) 0xdd, (byte) 0x12, (byte) 0xba, (byte) 0x87, + (byte) 0x99, (byte) 0x9c, (byte) 0xa3, (byte) 0x10, (byte) 0x12, + (byte) 0x9, (byte) 0xd2, (byte) 0xfb, (byte) 0x7, (byte) 0x19, + (byte) 0x5, (byte) 0x67, (byte) 0xcd, (byte) 0x97, (byte) 0x80, + (byte) 0x97, (byte) 0x83, (byte) 0xbf, (byte) 0xab, (byte) 0x99, + (byte) 0xf0, (byte) 0xce, (byte) 0x92, (byte) 0x6e, (byte) 0xe7, + (byte) 0x85, (byte) 0x70, (byte) 0xb, (byte) 0x7e, (byte) 0xb5, + (byte) 0x4b, (byte) 0x3b, (byte) 0x75, (byte) 0xbc, (byte) 0xbf, + (byte) 0x65, (byte) 0x49, (byte) 0xa8, (byte) 0xef, (byte) 0xf6, + (byte) 0xbf, (byte) 0x4e, (byte) 0xbd, (byte) 0x84, (byte) 0xda, + (byte) 0x38, (byte) 0x14, (byte) 0x1f, (byte) 0x86, (byte) 0x1f, + (byte) 0xac, (byte) 0xe3, (byte) 0x1e, (byte) 0xa1, (byte) 0x8a, + (byte) 0x63, (byte) 0xc8, (byte) 0xc3, (byte) 0x90, (byte) 0xa4, + (byte) 0x84, (byte) 0x8b, (byte) 0x5f, (byte) 0x5b, (byte) 0xc7, + (byte) 0xb9, (byte) 0xf8, (byte) 0x26, (byte) 0xca, (byte) 0x38, + (byte) 0x13, (byte) 0x7f, (byte) 0x22, (byte) 0x5a, (byte) 0x13, + (byte) 0xa6, (byte) 0xc2, (byte) 0x38, (byte) 0x5, (byte) 0x6d, + (byte) 0x1, (byte) 0x50, (byte) 0x4b, (byte) 0x7, (byte) 0x8, + (byte) 0x5a, (byte) 0xf1, (byte) 0x0, (byte) 0x98, (byte) 0xdd, + (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x67, (byte) 0x1, + (byte) 0x0, (byte) 0x0, (byte) 0x50, (byte) 0x4b, (byte) 0x1, + (byte) 0x2, (byte) 0x14, (byte) 0x0, (byte) 0x14, (byte) 0x0, + (byte) 0x8, (byte) 0x8, (byte) 0x8, (byte) 0x0, (byte) 0x17, + (byte) 0x71, (byte) 0x3b, (byte) 0x54, (byte) 0xc1, (byte) 0xfa, + (byte) 0x9d, (byte) 0xe2, (byte) 0x9e, (byte) 0x0, (byte) 0x0, + (byte) 0x0, (byte) 0xa6, (byte) 0x0, (byte) 0x0, (byte) 0x0, + (byte) 0x14, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, + (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, + (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, + (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x4d, (byte) 0x45, + (byte) 0x54, (byte) 0x41, (byte) 0x2d, (byte) 0x49, (byte) 0x4e, + (byte) 0x46, (byte) 0x2f, (byte) 0x4d, (byte) 0x41, (byte) 0x4e, + (byte) 0x49, (byte) 0x46, (byte) 0x45, (byte) 0x53, (byte) 0x54, + (byte) 0x2e, (byte) 0x4d, (byte) 0x46, (byte) 0x50, (byte) 0x4b, + (byte) 0x1, (byte) 0x2, (byte) 0x14, (byte) 0x0, (byte) 0x14, + (byte) 0x0, (byte) 0x8, (byte) 0x8, (byte) 0x8, (byte) 0x0, + (byte) 0x17, (byte) 0x71, (byte) 0x3b, (byte) 0x54, (byte) 0x8b, + (byte) 0xcb, (byte) 0xd5, (byte) 0xea, (byte) 0x3, (byte) 0x1, + (byte) 0x0, (byte) 0x0, (byte) 0x48, (byte) 0x1, (byte) 0x0, + (byte) 0x0, (byte) 0x14, (byte) 0x0, (byte) 0x0, (byte) 0x0, + (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, + (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, + (byte) 0xe0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x4d, + (byte) 0x45, (byte) 0x54, (byte) 0x41, (byte) 0x2d, (byte) 0x49, + (byte) 0x4e, (byte) 0x46, (byte) 0x2f, (byte) 0x4d, (byte) 0x59, + (byte) 0x46, (byte) 0x49, (byte) 0x52, (byte) 0x53, (byte) 0x54, + (byte) 0x4b, (byte) 0x2e, (byte) 0x53, (byte) 0x46, (byte) 0x50, + (byte) 0x4b, (byte) 0x1, (byte) 0x2, (byte) 0x14, (byte) 0x0, + (byte) 0x14, (byte) 0x0, (byte) 0x8, (byte) 0x8, (byte) 0x8, + (byte) 0x0, (byte) 0x17, (byte) 0x71, (byte) 0x3b, (byte) 0x54, + (byte) 0xba, (byte) 0x40, (byte) 0x24, (byte) 0x13, (byte) 0x4c, + (byte) 0x4, (byte) 0x0, (byte) 0x0, (byte) 0x58, (byte) 0x5, + (byte) 0x0, (byte) 0x0, (byte) 0x15, (byte) 0x0, (byte) 0x0, + (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, + (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, + (byte) 0x0, (byte) 0x25, (byte) 0x2, (byte) 0x0, (byte) 0x0, + (byte) 0x4d, (byte) 0x45, (byte) 0x54, (byte) 0x41, (byte) 0x2d, + (byte) 0x49, (byte) 0x4e, (byte) 0x46, (byte) 0x2f, (byte) 0x4d, + (byte) 0x59, (byte) 0x46, (byte) 0x49, (byte) 0x52, (byte) 0x53, + (byte) 0x54, (byte) 0x4b, (byte) 0x2e, (byte) 0x52, (byte) 0x53, + (byte) 0x41, (byte) 0x50, (byte) 0x4b, (byte) 0x1, (byte) 0x2, + (byte) 0x14, (byte) 0x0, (byte) 0x14, (byte) 0x0, (byte) 0x8, + (byte) 0x8, (byte) 0x8, (byte) 0x0, (byte) 0x6d, (byte) 0x73, + (byte) 0x3a, (byte) 0x54, (byte) 0x0, (byte) 0x0, (byte) 0x0, + (byte) 0x0, (byte) 0x2, (byte) 0x0, (byte) 0x0, (byte) 0x0, + (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x9, + (byte) 0x0, (byte) 0x4, (byte) 0x0, (byte) 0x0, (byte) 0x0, + (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, + (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0xb4, (byte) 0x6, + (byte) 0x0, (byte) 0x0, (byte) 0x4d, (byte) 0x45, (byte) 0x54, + (byte) 0x41, (byte) 0x2d, (byte) 0x49, (byte) 0x4e, (byte) 0x46, + (byte) 0x2f, (byte) 0xfe, (byte) 0xca, (byte) 0x0, (byte) 0x0, + (byte) 0x50, (byte) 0x4b, (byte) 0x1, (byte) 0x2, (byte) 0x14, + (byte) 0x0, (byte) 0x14, (byte) 0x0, (byte) 0x8, (byte) 0x8, + (byte) 0x8, (byte) 0x0, (byte) 0x6c, (byte) 0xb1, (byte) 0x38, + (byte) 0x3e, (byte) 0x5a, (byte) 0xf1, (byte) 0x0, (byte) 0x98, + (byte) 0xdd, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x67, + (byte) 0x1, (byte) 0x0, (byte) 0x0, (byte) 0x1c, (byte) 0x0, + (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, + (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, + (byte) 0x0, (byte) 0x0, (byte) 0xf1, (byte) 0x6, (byte) 0x0, + (byte) 0x0, (byte) 0x6a, (byte) 0x61, (byte) 0x76, (byte) 0x61, + (byte) 0x78, (byte) 0x2f, (byte) 0x69, (byte) 0x6e, (byte) 0x6a, + // We will modify 0x53, "S", within the CEN filename entry + (byte) 0x65, (byte) 0x63, (byte) 0x74, (byte) 0x2f, (byte) 0x53, + (byte) 0x69, (byte) 0x6e, (byte) 0x67, (byte) 0x6c, (byte) 0x65, + (byte) 0x74, (byte) 0x6f, (byte) 0x6e, (byte) 0x2e, (byte) 0x63, + (byte) 0x6c, (byte) 0x61, (byte) 0x73, (byte) 0x73, (byte) 0x50, + (byte) 0x4b, (byte) 0x5, (byte) 0x6, (byte) 0x0, (byte) 0x0, + (byte) 0x0, (byte) 0x0, (byte) 0x5, (byte) 0x0, (byte) 0x5, + (byte) 0x0, (byte) 0x4c, (byte) 0x1, (byte) 0x0, (byte) 0x0, + (byte) 0x18, (byte) 0x8, (byte) 0x0, (byte) 0x0, (byte) 0x0, + (byte) 0x0, + }; + + /** + * DataProvider used to specify valid jars and whether to verify them + * + * @return Entry object indicating the jar file and whether it will be verified + */ + @DataProvider + public Object[][] validJars() { + return new Object[][]{ + {SIGNED_VALID_ENTRY_NAME_JAR, true}, + {SIGNED_VALID_ENTRY_NAME_JAR, false}, + {VALID_ENTRY_NAME_JAR, true}, + {VALID_ENTRY_NAME_JAR, false}, + }; + } + + /** + * DataProvider used to specify invalid jars and whether to verify them + * + * @return Entry object indicating the jar file and whether it will be verified + */ + @DataProvider + public Object[][] inValidJars() { + return new Object[][]{ + {SIGNED_INVALID_ENTRY_NAME_JAR, true}, + {SIGNED_INVALID_ENTRY_NAME_JAR, false}, + {INVALID_ENTRY_NAME_JAR, true}, + {INVALID_ENTRY_NAME_JAR, false}, + }; + } + + /** + * Create Jar files used by the tests. + * + * The {@code byte} arrays {@code VALID_ENTRY_NAME_JAR} and + * {@code SIGNED-VALID_ENTRY_NAME_JAR} are written to disk to create the jar + * files: {@code Valid-EntryName.jar} and {@code Signed-Valid-EntryName.jar}. + * + * The jar files {@code Invalid-EntryName.jar} and + * {@code Signed-Invalid-EntryName.jar} are created by copying the + * {@code byte} arrays {@code VALID_ENTRY_NAME} and + * {@code SIGNED-VALID_ENTRY_NAME} and modifying + * the CEN filename entry, "javax/inject/Singleton.class", changing the + * first character from {@code 0x53}, "S", to the {@code 0x13}. + * + * @throws IOException If an error occurs + * + */ + @BeforeTest + public static void setup() throws IOException { + + // Create valid jar + Files.deleteIfExists(VALID_ENTRY_NAME_JAR); + Files.write(VALID_ENTRY_NAME_JAR, VALID_ENTRY_NAME); + + // Create valid signed jar + Files.deleteIfExists(SIGNED_VALID_ENTRY_NAME_JAR); + Files.write(SIGNED_VALID_ENTRY_NAME_JAR, SIGNED_VALID_ENTRY_NAME); + + // Create a JAR file with the invalid entry name + Files.deleteIfExists(INVALID_ENTRY_NAME_JAR); + // Make a copy of the byte array containing the valid entry name + byte[] invalid_bytes = Arrays.copyOf(VALID_ENTRY_NAME, VALID_ENTRY_NAME.length); + // Change from 0x53, "S", to an invalid UTF8 character, 0x13 + invalid_bytes[VALID_ENTRY_NAME.length - SINGLETON_CEN_FILENAME_OFFSET] = + INVALID_UTF8_BYTE; + Files.write(INVALID_ENTRY_NAME_JAR, invalid_bytes); + + // Create a signed JAR file with the invalid entry name + Files.deleteIfExists(SIGNED_INVALID_ENTRY_NAME_JAR); + // Make a copy of the byte array containing the valid entry name + invalid_bytes = Arrays.copyOf(SIGNED_VALID_ENTRY_NAME, + SIGNED_VALID_ENTRY_NAME.length); + // Change from 0x53, "S", to an invalid UTF8 character, 0x13 + invalid_bytes[SIGNED_VALID_ENTRY_NAME.length - SINGLETON_CEN_FILENAME_OFFSET] = + INVALID_UTF8_BYTE; + Files.write(SIGNED_INVALID_ENTRY_NAME_JAR, invalid_bytes); + } + + /** + * Clean up after the test run + * + * @throws IOException If an error occurs + */ + @AfterTest + public static void cleanup() throws IOException { + Files.deleteIfExists(VALID_ENTRY_NAME_JAR); + Files.deleteIfExists(SIGNED_VALID_ENTRY_NAME_JAR); + Files.deleteIfExists(INVALID_ENTRY_NAME_JAR); + Files.deleteIfExists(SIGNED_INVALID_ENTRY_NAME_JAR); + } + + /** + * Validate that the CEN filename to be modified can be accessed in + * the original jar when the file is opened using JarFile and accessed via + * a ZipEntry + * + * @param jar the jar file to be used + * @param verify indicates whether the jar should be verified + * @throws Exception if an error occurs + */ + @Test(dataProvider = "validJars") + public static void validJarFileZipEntryTest(Path jar, boolean verify) throws Exception { + try (JarFile jf = new JarFile(jar.toFile(), verify)) { + ZipEntry ze = jf.getEntry(CEN_FILENAME_TO_MODIFY); + var is = jf.getInputStream(ze); + byte[] cnt = is.readAllBytes(); + assertNotNull(cnt); + } + } + + /** + * Validate that the CEN filename to be modified can be accessed in + * the original jar when the file is opened using JarFile and accessed via + * a JarEntry + * + * @param jar the jar file to be used + * @param verify indicates whether the jar should be verified + * @throws Exception if an error occurs + */ + @Test(dataProvider = "validJars") + public static void validJarFileJarEntryTest(Path jar, boolean verify) throws Exception { + try (JarFile jf = new JarFile(jar.toFile(), verify)) { + ZipEntry ze = jf.getEntry(CEN_FILENAME_TO_MODIFY); + var is = jf.getInputStream(ze); + byte[] cnt = is.readAllBytes(); + assertNotNull(cnt); + } + } + + /** + * Validate that the CEN filename to be modified can be accessed in + * the original jar when the file is opened using ZipFile + * + * @param jar the jar file to be used + * @param verify indicates whether the jar should be verified(not used) + * @throws Exception if an error occurs + */ + @Test(dataProvider = "validJars") + public static void validZipFileZipEntryTest(Path jar, boolean verify) throws Exception { + try (ZipFile jf = new ZipFile(jar.toFile())) { + ZipEntry ze = jf.getEntry(CEN_FILENAME_TO_MODIFY); + var is = jf.getInputStream(ze); + byte[] cnt = is.readAllBytes(); + assertNotNull(cnt); + } + } + + /** + * Validate that a NullPointerException is thrown by JarFile::getInputStream + * when the specified ZipEntry is null. + * + * @param jar the jar file to be used + * @param verify indicates whether the jar should be verified(not used) + * @throws Exception if an error occurs + */ + @Test(dataProvider = "inValidJars") + public static void invalidJarFileZipEntry(Path jar, boolean verify) throws Exception { + try (JarFile jf = new JarFile(jar.toFile(), verify)) { + // The entry will not be found resulting in the ZipEntry being null + ZipEntry ze = jf.getEntry(CEN_FILENAME_TO_MODIFY); + var ex= expectThrows(NullPointerException.class, + () -> jf.getInputStream(ze) ); + // Validate that we receive the expected message from Objects.requireNonNull + assertTrue( ex != null && ex.getMessage().equals("ze")); + } + } + + /** + * Validate that a NullPointerException is thrown by ZipFile::getInputStream + * when the specified ZipEntry is null. + * @param jar the jar file to be used + * @param verify indicates whether the jar should be verified(not used) + * @throws IOException if an error occurs + */ + @Test(dataProvider = "inValidJars") + public static void invalidZipFileZipEntry(Path jar, boolean verify) throws Exception { + try (ZipFile jf = new ZipFile(jar.toFile())) { + // The entry will not be found resulting in the ZipEntry being null + ZipEntry ze = jf.getEntry(CEN_FILENAME_TO_MODIFY); + var ex= expectThrows(NullPointerException.class, + () -> jf.getInputStream(ze) ); + // Validate that we receive the expected message from Objects.requireNonNull + assertTrue( ex != null && ex.getMessage().equals("entry")); + } + } + + /** + * Validate that JarFile::getInputStream will return null when the specified + * ZipEntry does not exist in the Jar file + * + * @param jar the jar file to be used + * @param verify indicates whether the jar should be verified + * @throws Exception if an error occurs + */ + @Test(dataProvider = "validJars") + public static void JarFileZipEntryDoesNotExistGetInputStreamTest( + Path jar, boolean verify) throws Exception { + + try (JarFile jf = new JarFile(jar.toFile(), verify)) { + var ze = new ZipEntry(ZIP_ENTRY_THAT_DOES_NOT_EXIST); + var is = jf.getInputStream(ze); + // As the ZipEntry cannot be found, the returned InputStream is null + assertNull(is); + } + } + + /** + * Validate that ZipFile::getInputStream will return null when the specified + * ZipEntry does not exist in the Jar file + * @param jar the jar file to be used + * @param verify indicates whether the jar should be verified(not used) + * @throws Exception if an error occurs + */ + @Test(dataProvider = "validJars") + public static void ZipFileZipEntryDoesNotExistGetInputStreamTest( + Path jar, boolean verify) throws Exception { + try (ZipFile jf = new ZipFile(jar.toFile())) { + var ze = new ZipEntry(ZIP_ENTRY_THAT_DOES_NOT_EXIST); + var is = jf.getInputStream(ze); + // As the ZipEntry cannot be found, the returned InputStream is null + assertNull(is); + } + } + + /** + * Validate that JarFile::getInputStream will return null when the specified + * JarEntry does not exist in the Jar file + * @param jar the jar file to be used + * @param verify indicates whether the jar should be verified + * @throws Exception if an error occurs + */ + @Test(dataProvider = "validJars") + public static void JarFileJarEntryEntryDoesNotExistGetInputStreamTest ( + Path jar, boolean verify) throws Exception { + try (JarFile jf = new JarFile(jar.toFile(), verify)) { + var je = new JarEntry(ZIP_ENTRY_THAT_DOES_NOT_EXIST); + var is = jf.getInputStream(je); + // As the JarEntry cannot be found, the returned InputStream is null + assertNull(is); + } + } + + /** + * Validate that JarFile::getInputStream will return null when validating + * a signed jar and the ZipEntry passed as a parameter returns null + * when ZipEntry::getName is invoked. + * @param jar the jar file to be used + * @param verify indicates whether the jar should be verified + * @throws Exception if an error occurs + */ + @Test(dataProvider = "validJars") + public static void JarFileZipEntryGetNameNullTest(Path jar, boolean verify) throws Exception { + + // Signed Jar is used for the next checks + try (JarFile jf = new JarFile(jar.toFile(), verify)) { + var ze = new InvalidZipEntry(CEN_FILENAME_TO_MODIFY); + var is = jf.getInputStream(ze); + // As the ZipEntry cannot be found, the returned InputStream is null + assertNull(is); + } + } + + /** + * Utility method which takes a byte array and converts to byte array + * declaration. For example: + *
+     *     {@code
+     *        var fooJar = Files.readAllBytes(Path.of("foo.jar"));
+     *        var result = createByteArray(fooJar, "FOO_BYTES");
+     *      }
+     * 
+ * + * @param bytes A byte array used to create a byte array declaration + * @param name Name to be used in the byte array declaration + * @return The formatted byte array declaration + */ + public static String createByteArray(byte[] bytes, String name) { + StringBuilder sb = new StringBuilder(bytes.length * 5); + Formatter fmt = new Formatter(sb); + fmt.format(" public static byte[] %s = {", name); + final int length = 5; + for (int i = 0; i < bytes.length; i++) { + if (i % length == 0) { + fmt.format("%n "); + } + fmt.format(" (byte) 0x%x,", bytes[i] & 0xff); + } + fmt.format("%n };%n"); + return sb.toString(); + } + + /** + * Overridden ZipEntry class which specifies an invalid name for the + * ZipEntry and will always return null for the Zip entry name + */ + public static class InvalidZipEntry extends ZipEntry { + public InvalidZipEntry(String name) { + super(ZIP_ENTRY_THAT_DOES_NOT_EXIST); + } + public String getName() { + return null; + } + } +} diff --git a/test/jdk/java/util/zip/ZipFile/InvalidCommentLengthTest.java b/test/jdk/java/util/zip/ZipFile/InvalidCommentLengthTest.java new file mode 100644 index 0000000000000000000000000000000000000000..1910107f0d39bd1d6e18ef47181b9f9782c5c85a --- /dev/null +++ b/test/jdk/java/util/zip/ZipFile/InvalidCommentLengthTest.java @@ -0,0 +1,345 @@ +/* + * 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.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.util.Arrays; +import java.util.jar.JarFile; +import java.util.zip.ZipEntry; +import java.util.zip.ZipException; +import java.util.zip.ZipFile; + +import static org.testng.Assert.*; + +/** + * @test + * @bug 8280404 + * @summary Validate that Zip/JarFile will throw a ZipException when the CEN + * comment length field contains an incorrect value + * @run testng/othervm InvalidCommentLengthTest + */ +public class InvalidCommentLengthTest { + + // Name used to create a JAR with an invalid comment length + public static final Path INVALID_CEN_COMMENT_LENGTH_JAR = + Path.of("Invalid-CEN-Comment-Length.jar"); + // Name used to create a JAR with a valid comment length + public static final Path VALID_CEN_COMMENT_LENGTH_JAR = + Path.of("Valid-CEN-Comment-Length.jar"); + // Zip/Jar CEN file header entry that will be modified + public static final String META_INF_MANIFEST_MF = "META-INF/MANIFEST.MF"; + // Expected ZipException message when the comment length corrupts the + // Zip/Jar file + public static final String INVALID_CEN_HEADER_BAD_ENTRY_NAME_OR_COMMENT = + "invalid CEN header (bad entry name or comment)"; + + /** + * Byte array representing a valid jar file prior modifying the comment length + * entry in a CEN file header. + * The "Valid-CEN-Comment-Length.jar" jar file was created via: + *
+     *     {@code
+     *     jar cvf Valid-CEN-Comment-Length.jar Hello.txt Tennis.txt BruceWayne.txt
+     *     added manifest
+     *     adding: Hello.txt(in = 12) (out= 14)(deflated -16%)
+     *     adding: Tennis.txt(in = 53) (out= 53)(deflated 0%)
+     *     adding: BruceWayne.txt(in = 12) (out= 14)(deflated -16%)
+     *     }
+     * 
+ * Its contents are: + *
+     *     {@code
+     *     jar tvf Valid-CEN-Comment-Length.jar
+     *      0 Wed Mar 02 06:39:24 EST 2022 META-INF/
+     *     66 Wed Mar 02 06:39:24 EST 2022 META-INF/MANIFEST.MF
+     *     12 Wed Mar 02 06:39:06 EST 2022 Hello.txt
+     *     53 Wed Mar 02 13:04:48 EST 2022 Tennis.txt
+     *     12 Wed Mar 02 15:15:34 EST 2022 BruceWayne.txt
+     *     }
+     * 
+ * The ByteArray was created by: + *
+     *  {@code
+     *     var jar = Files.readAllBytes("Valid-CEN-Comment-Length.jar");
+     *     var validEntryName = createByteArray(fooJar,
+     *           "VALID_ZIP_WITH_NO_COMMENTS_BYTES");
+     *  }
+     * 
+ */ + public static byte[] VALID_ZIP_WITH_NO_COMMENTS_BYTES = { + (byte) 0x50, (byte) 0x4b, (byte) 0x3, (byte) 0x4, (byte) 0x14, + (byte) 0x0, (byte) 0x8, (byte) 0x8, (byte) 0x8, (byte) 0x0, + (byte) 0xec, (byte) 0x34, (byte) 0x62, (byte) 0x54, (byte) 0x0, + (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, + (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, + (byte) 0x0, (byte) 0x9, (byte) 0x0, (byte) 0x4, (byte) 0x0, + (byte) 0x4d, (byte) 0x45, (byte) 0x54, (byte) 0x41, (byte) 0x2d, + (byte) 0x49, (byte) 0x4e, (byte) 0x46, (byte) 0x2f, (byte) 0xfe, + (byte) 0xca, (byte) 0x0, (byte) 0x0, (byte) 0x3, (byte) 0x0, + (byte) 0x50, (byte) 0x4b, (byte) 0x7, (byte) 0x8, (byte) 0x0, + (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x2, (byte) 0x0, + (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, + (byte) 0x0, (byte) 0x50, (byte) 0x4b, (byte) 0x3, (byte) 0x4, + (byte) 0x14, (byte) 0x0, (byte) 0x8, (byte) 0x8, (byte) 0x8, + (byte) 0x0, (byte) 0xec, (byte) 0x34, (byte) 0x62, (byte) 0x54, + (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, + (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, + (byte) 0x0, (byte) 0x0, (byte) 0x14, (byte) 0x0, (byte) 0x0, + (byte) 0x0, (byte) 0x4d, (byte) 0x45, (byte) 0x54, (byte) 0x41, + (byte) 0x2d, (byte) 0x49, (byte) 0x4e, (byte) 0x46, (byte) 0x2f, + (byte) 0x4d, (byte) 0x41, (byte) 0x4e, (byte) 0x49, (byte) 0x46, + (byte) 0x45, (byte) 0x53, (byte) 0x54, (byte) 0x2e, (byte) 0x4d, + (byte) 0x46, (byte) 0xf3, (byte) 0x4d, (byte) 0xcc, (byte) 0xcb, + (byte) 0x4c, (byte) 0x4b, (byte) 0x2d, (byte) 0x2e, (byte) 0xd1, + (byte) 0xd, (byte) 0x4b, (byte) 0x2d, (byte) 0x2a, (byte) 0xce, + (byte) 0xcc, (byte) 0xcf, (byte) 0xb3, (byte) 0x52, (byte) 0x30, + (byte) 0xd4, (byte) 0x33, (byte) 0xe0, (byte) 0xe5, (byte) 0x72, + (byte) 0x2e, (byte) 0x4a, (byte) 0x4d, (byte) 0x2c, (byte) 0x49, + (byte) 0x4d, (byte) 0xd1, (byte) 0x75, (byte) 0xaa, (byte) 0x4, + (byte) 0xa, (byte) 0x98, (byte) 0xe8, (byte) 0x19, (byte) 0xe8, + (byte) 0x19, (byte) 0x2a, (byte) 0x68, (byte) 0xf8, (byte) 0x17, + (byte) 0x25, (byte) 0x26, (byte) 0xe7, (byte) 0xa4, (byte) 0x2a, + (byte) 0x38, (byte) 0xe7, (byte) 0x17, (byte) 0x15, (byte) 0xe4, + (byte) 0x17, (byte) 0x25, (byte) 0x96, (byte) 0x0, (byte) 0x15, + (byte) 0x6b, (byte) 0xf2, (byte) 0x72, (byte) 0xf1, (byte) 0x72, + (byte) 0x1, (byte) 0x0, (byte) 0x50, (byte) 0x4b, (byte) 0x7, + (byte) 0x8, (byte) 0xf4, (byte) 0x59, (byte) 0xdc, (byte) 0xa6, + (byte) 0x42, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x42, + (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x50, (byte) 0x4b, + (byte) 0x3, (byte) 0x4, (byte) 0x14, (byte) 0x0, (byte) 0x8, + (byte) 0x8, (byte) 0x8, (byte) 0x0, (byte) 0xe3, (byte) 0x34, + (byte) 0x62, (byte) 0x54, (byte) 0x0, (byte) 0x0, (byte) 0x0, + (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, + (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x9, + (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x48, (byte) 0x65, + (byte) 0x6c, (byte) 0x6c, (byte) 0x6f, (byte) 0x2e, (byte) 0x74, + (byte) 0x78, (byte) 0x74, (byte) 0xf3, (byte) 0x48, (byte) 0xcd, + (byte) 0xc9, (byte) 0xc9, (byte) 0x57, (byte) 0x28, (byte) 0xcf, + (byte) 0x2f, (byte) 0xca, (byte) 0x49, (byte) 0xe1, (byte) 0x2, + (byte) 0x0, (byte) 0x50, (byte) 0x4b, (byte) 0x7, (byte) 0x8, + (byte) 0xd5, (byte) 0xe0, (byte) 0x39, (byte) 0xb7, (byte) 0xe, + (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0xc, (byte) 0x0, + (byte) 0x0, (byte) 0x0, (byte) 0x50, (byte) 0x4b, (byte) 0x3, + (byte) 0x4, (byte) 0x14, (byte) 0x0, (byte) 0x8, (byte) 0x8, + (byte) 0x8, (byte) 0x0, (byte) 0x98, (byte) 0x68, (byte) 0x62, + (byte) 0x54, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, + (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, + (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0xa, (byte) 0x0, + (byte) 0x0, (byte) 0x0, (byte) 0x54, (byte) 0x65, (byte) 0x6e, + (byte) 0x6e, (byte) 0x69, (byte) 0x73, (byte) 0x2e, (byte) 0x74, + (byte) 0x78, (byte) 0x74, (byte) 0x73, (byte) 0xf2, (byte) 0xb, + (byte) 0x50, (byte) 0x8, (byte) 0x48, (byte) 0x2c, (byte) 0xca, + (byte) 0x4c, (byte) 0x4a, (byte) 0x2c, (byte) 0x56, (byte) 0xf0, + (byte) 0x2f, (byte) 0x48, (byte) 0xcd, (byte) 0x53, (byte) 0xc8, + (byte) 0x2c, (byte) 0x56, (byte) 0x48, (byte) 0x54, (byte) 0x48, + (byte) 0x2b, (byte) 0xcd, (byte) 0x53, (byte) 0x8, (byte) 0x49, + (byte) 0xcd, (byte) 0xcb, (byte) 0x3, (byte) 0x72, (byte) 0x42, + (byte) 0xf2, (byte) 0x4b, (byte) 0x8b, (byte) 0xf2, (byte) 0x12, + (byte) 0x73, (byte) 0x53, (byte) 0xf3, (byte) 0x4a, (byte) 0x14, + (byte) 0x4a, (byte) 0xf2, (byte) 0x15, (byte) 0xca, (byte) 0x13, + (byte) 0x4b, (byte) 0x92, (byte) 0x33, (byte) 0xb8, (byte) 0x0, + (byte) 0x50, (byte) 0x4b, (byte) 0x7, (byte) 0x8, (byte) 0xaa, + (byte) 0xad, (byte) 0x14, (byte) 0xd, (byte) 0x35, (byte) 0x0, + (byte) 0x0, (byte) 0x0, (byte) 0x35, (byte) 0x0, (byte) 0x0, + (byte) 0x0, (byte) 0x50, (byte) 0x4b, (byte) 0x3, (byte) 0x4, + (byte) 0x14, (byte) 0x0, (byte) 0x8, (byte) 0x8, (byte) 0x8, + (byte) 0x0, (byte) 0xf1, (byte) 0x79, (byte) 0x62, (byte) 0x54, + (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, + (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, + (byte) 0x0, (byte) 0x0, (byte) 0xe, (byte) 0x0, (byte) 0x0, + (byte) 0x0, (byte) 0x42, (byte) 0x72, (byte) 0x75, (byte) 0x63, + (byte) 0x65, (byte) 0x57, (byte) 0x61, (byte) 0x79, (byte) 0x6e, + (byte) 0x65, (byte) 0x2e, (byte) 0x74, (byte) 0x78, (byte) 0x74, + (byte) 0xf3, (byte) 0x54, (byte) 0x48, (byte) 0xcc, (byte) 0x55, + (byte) 0x70, (byte) 0x4a, (byte) 0x2c, (byte) 0xc9, (byte) 0x4d, + (byte) 0xcc, (byte) 0xe3, (byte) 0x2, (byte) 0x0, (byte) 0x50, + (byte) 0x4b, (byte) 0x7, (byte) 0x8, (byte) 0x6c, (byte) 0x70, + (byte) 0x60, (byte) 0xbd, (byte) 0xe, (byte) 0x0, (byte) 0x0, + (byte) 0x0, (byte) 0xc, (byte) 0x0, (byte) 0x0, (byte) 0x0, + (byte) 0x50, (byte) 0x4b, (byte) 0x1, (byte) 0x2, (byte) 0x14, + (byte) 0x0, (byte) 0x14, (byte) 0x0, (byte) 0x8, (byte) 0x8, + (byte) 0x8, (byte) 0x0, (byte) 0xec, (byte) 0x34, (byte) 0x62, + (byte) 0x54, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, + (byte) 0x2, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, + (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x9, (byte) 0x0, + (byte) 0x4, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, + (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, + (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, + (byte) 0x0, (byte) 0x4d, (byte) 0x45, (byte) 0x54, (byte) 0x41, + (byte) 0x2d, (byte) 0x49, (byte) 0x4e, (byte) 0x46, (byte) 0x2f, + (byte) 0xfe, (byte) 0xca, (byte) 0x0, (byte) 0x0, (byte) 0x50, + (byte) 0x4b, (byte) 0x1, (byte) 0x2, (byte) 0x14, (byte) 0x0, + (byte) 0x14, (byte) 0x0, (byte) 0x8, (byte) 0x8, (byte) 0x8, + (byte) 0x0, (byte) 0xec, (byte) 0x34, (byte) 0x62, (byte) 0x54, + (byte) 0xf4, (byte) 0x59, (byte) 0xdc, (byte) 0xa6, (byte) 0x42, + (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x42, (byte) 0x0, + (byte) 0x0, (byte) 0x0, (byte) 0x14, (byte) 0x0, (byte) 0x0, + (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, + (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, + (byte) 0x0, (byte) 0x3d, (byte) 0x0, (byte) 0x0, (byte) 0x0, + (byte) 0x4d, (byte) 0x45, (byte) 0x54, (byte) 0x41, (byte) 0x2d, + (byte) 0x49, (byte) 0x4e, (byte) 0x46, (byte) 0x2f, (byte) 0x4d, + (byte) 0x41, (byte) 0x4e, (byte) 0x49, (byte) 0x46, (byte) 0x45, + (byte) 0x53, (byte) 0x54, (byte) 0x2e, (byte) 0x4d, (byte) 0x46, + (byte) 0x50, (byte) 0x4b, (byte) 0x1, (byte) 0x2, (byte) 0x14, + (byte) 0x0, (byte) 0x14, (byte) 0x0, (byte) 0x8, (byte) 0x8, + (byte) 0x8, (byte) 0x0, (byte) 0xe3, (byte) 0x34, (byte) 0x62, + (byte) 0x54, (byte) 0xd5, (byte) 0xe0, (byte) 0x39, (byte) 0xb7, + (byte) 0xe, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0xc, + (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x9, (byte) 0x0, + (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, + (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, + (byte) 0x0, (byte) 0x0, (byte) 0xc1, (byte) 0x0, (byte) 0x0, + (byte) 0x0, (byte) 0x48, (byte) 0x65, (byte) 0x6c, (byte) 0x6c, + (byte) 0x6f, (byte) 0x2e, (byte) 0x74, (byte) 0x78, (byte) 0x74, + (byte) 0x50, (byte) 0x4b, (byte) 0x1, (byte) 0x2, (byte) 0x14, + (byte) 0x0, (byte) 0x14, (byte) 0x0, (byte) 0x8, (byte) 0x8, + (byte) 0x8, (byte) 0x0, (byte) 0x98, (byte) 0x68, (byte) 0x62, + (byte) 0x54, (byte) 0xaa, (byte) 0xad, (byte) 0x14, (byte) 0xd, + (byte) 0x35, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x35, + (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0xa, (byte) 0x0, + (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, + (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, + (byte) 0x0, (byte) 0x0, (byte) 0x6, (byte) 0x1, (byte) 0x0, + (byte) 0x0, (byte) 0x54, (byte) 0x65, (byte) 0x6e, (byte) 0x6e, + (byte) 0x69, (byte) 0x73, (byte) 0x2e, (byte) 0x74, (byte) 0x78, + (byte) 0x74, (byte) 0x50, (byte) 0x4b, (byte) 0x1, (byte) 0x2, + (byte) 0x14, (byte) 0x0, (byte) 0x14, (byte) 0x0, (byte) 0x8, + (byte) 0x8, (byte) 0x8, (byte) 0x0, (byte) 0xf1, (byte) 0x79, + (byte) 0x62, (byte) 0x54, (byte) 0x6c, (byte) 0x70, (byte) 0x60, + (byte) 0xbd, (byte) 0xe, (byte) 0x0, (byte) 0x0, (byte) 0x0, + (byte) 0xc, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0xe, + (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, + (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, + (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x73, (byte) 0x1, + (byte) 0x0, (byte) 0x0, (byte) 0x42, (byte) 0x72, (byte) 0x75, + (byte) 0x63, (byte) 0x65, (byte) 0x57, (byte) 0x61, (byte) 0x79, + (byte) 0x6e, (byte) 0x65, (byte) 0x2e, (byte) 0x74, (byte) 0x78, + (byte) 0x74, (byte) 0x50, (byte) 0x4b, (byte) 0x5, (byte) 0x6, + (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x5, + (byte) 0x0, (byte) 0x5, (byte) 0x0, (byte) 0x28, (byte) 0x1, + (byte) 0x0, (byte) 0x0, (byte) 0xbd, (byte) 0x1, (byte) 0x0, + (byte) 0x0, (byte) 0x0, (byte) 0x0, + }; + + /** + * Create Jar files used by the tests. + * The {@code byte} array {@code VALID_ZIP_WITH_NO_COMMENTS_BYTES} is written + * to disk to create the jar file: {@code Valid-CEN-Comment-Length.jar}. + * + * The jar file {@code InValid-CEN-Comment-Length.jar} is created by copying + * the {@code byte} array {@code VALID_ZIP_WITH_NO_COMMENTS_BYTES} and modifying + * the CEN file header comment length entry for "META-INF/MANIFEST.MF" so that + * new comment length will forward the CEN to a subsequent CEN file header + * entry. + * + * For {@code InValid-CEN-Comment-Length.jar}, the comment length is changed + * from {@code 0x0} to the {@code 0x37}. + * + * @throws IOException If an error occurs + */ + @BeforeTest + public void setup() throws IOException { + Files.deleteIfExists(VALID_CEN_COMMENT_LENGTH_JAR); + Files.deleteIfExists(INVALID_CEN_COMMENT_LENGTH_JAR); + // Create the valid jar + Files.write(VALID_CEN_COMMENT_LENGTH_JAR, VALID_ZIP_WITH_NO_COMMENTS_BYTES); + // Now create an invalid jar + byte[] invalid_bytes = Arrays.copyOf(VALID_ZIP_WITH_NO_COMMENTS_BYTES, + VALID_ZIP_WITH_NO_COMMENTS_BYTES.length); + // Change CEN file Header comment length so that the length will + // result in the offset pointing to a subsequent CEN file header + // resulting in an invalid comment + invalid_bytes[536] = 55; + Files.write(INVALID_CEN_COMMENT_LENGTH_JAR, invalid_bytes); + } + + /** + * Clean up after the test run + * + * @throws IOException If an error occurs + */ + @AfterTest + public static void cleanup() throws IOException { + Files.deleteIfExists(VALID_CEN_COMMENT_LENGTH_JAR); + Files.deleteIfExists(INVALID_CEN_COMMENT_LENGTH_JAR); + } + + /** + * Validate that the original(valid) Jar file can be opened by {@code ZipFile} + * and the expected Zip entry can be found + * @throws IOException If an error occurs + */ + @Test + public static void ZipFileValidCommentLengthTest() throws IOException { + try (ZipFile jf = new ZipFile(VALID_CEN_COMMENT_LENGTH_JAR.toFile())) { + ZipEntry ze = jf.getEntry(META_INF_MANIFEST_MF); + assertNotNull(ze); + assertEquals(ze.getName(), META_INF_MANIFEST_MF); + } + } + + /** + * Validate that the original(valid) Jar file can be opened by {@code JarFile} + * and the expected Zip entry can be found + * @throws IOException If an error occurs + */ + @Test + public static void JarFileValidCommentLengthTest() throws IOException { + try (JarFile jf = new JarFile(VALID_CEN_COMMENT_LENGTH_JAR.toFile())) { + ZipEntry ze = jf.getEntry(META_INF_MANIFEST_MF); + assertNotNull(ze); + assertEquals(ze.getName(), META_INF_MANIFEST_MF); + } + } + + /** + * Validate that a ZipException is thrown when the CEN file header comment + * length is non-zero and the CEN entry does not contain a comment when + * the Jar file is opened by {@code ZipFile} + */ + @Test + public static void ZipFileInValidCommentLengthTest() { + var ex= expectThrows(ZipException.class, + () -> new ZipFile(INVALID_CEN_COMMENT_LENGTH_JAR.toFile())); + assertEquals(ex.getMessage(), INVALID_CEN_HEADER_BAD_ENTRY_NAME_OR_COMMENT); + } + + /** + * Validate that a ZipException is thrown when the CEN file header comment + * length is non-zero and the CEN entry does not contain a comment when + * the Jar file is opened by {@code JarFile} + */ + @Test + public static void JarFileInValidCommentLengthTest() { + var ex= expectThrows(ZipException.class, + () -> new JarFile(INVALID_CEN_COMMENT_LENGTH_JAR.toFile())); + assertEquals(ex.getMessage(), INVALID_CEN_HEADER_BAD_ENTRY_NAME_OR_COMMENT); + } +} diff --git a/test/jdk/javax/accessibility/4715503/AccessibleJTableCellBoundingRectangleTest.java b/test/jdk/javax/accessibility/4715503/AccessibleJTableCellBoundingRectangleTest.java new file mode 100644 index 0000000000000000000000000000000000000000..716925a51e66dd79abde28407048032746beffdc --- /dev/null +++ b/test/jdk/javax/accessibility/4715503/AccessibleJTableCellBoundingRectangleTest.java @@ -0,0 +1,91 @@ +/* + * 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 headful + * @bug 4715503 + * @summary AccessibleTable cannot get the Bounding Rectangle of Table Header Cells. + * @run main AccessibleJTableCellBoundingRectangleTest + */ + +import java.awt.Rectangle; +import java.awt.Robot; + +import javax.swing.JFrame; +import javax.swing.JTable; +import javax.swing.SwingUtilities; + +public class AccessibleJTableCellBoundingRectangleTest { + private static JTable jTable; + private static JFrame jFrame; + + private static Object[][] rowData = { { "01", "02", "03", "04", "05" }, + { "11", "12", "13", "14", "15" }, { "21", "22", "23", "24", "25" }, + { "31", "32", "33", "34", "35" }, { "41", "42", "43", "44", "45" } }; + + private static Object[] colNames = { "1", "2", "3", "4", "5" }; + + private static void doTest() throws Exception { + try { + SwingUtilities.invokeAndWait(() -> createGUI()); + Robot robot = new Robot(); + robot.setAutoDelay(500); + robot.waitForIdle(); + + for (int i = 0; i <= colNames.length - 1; i++) { + try { + Rectangle bounds = + jTable.getTableHeader().getAccessibleContext().getAccessibleChild(i) + .getAccessibleContext().getAccessibleComponent().getBounds(); + + if (bounds != null) { + System.out.println("Column " + i + " Bounds: " + bounds); + } else { + throw new RuntimeException( + "Bounding Rectangles getting bounding rectangle for table header cells is null"); + } + } catch (Exception e) { + throw new RuntimeException("Bounding Rectangles getting bounding rectangle for " + + "table header cells threw an exception:\n" + e); + } + } + } finally { + SwingUtilities.invokeAndWait(() -> jFrame.dispose()); + } + } + + private static void createGUI() { + jTable = new JTable(rowData, colNames); + jFrame = new JFrame(); + jFrame.setBounds(100, 100, 300, 300); + jFrame.getContentPane().add(jTable); + jFrame.setVisible(true); + } + + public static void main(String args[]) throws Exception { + doTest(); + System.out.println("Test Passed"); + } +} + diff --git a/test/jdk/javax/accessibility/JTable/BooleanRendererHasAccessibleActionTest.java b/test/jdk/javax/accessibility/JTable/BooleanRendererHasAccessibleActionTest.java new file mode 100644 index 0000000000000000000000000000000000000000..79f16e3c3660489e729af80d0c859e1e237ec008 --- /dev/null +++ b/test/jdk/javax/accessibility/JTable/BooleanRendererHasAccessibleActionTest.java @@ -0,0 +1,192 @@ +/* + * 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 8277922 + @key headful + @summary TableCellRenderer of JTable cell with Boolean data should not + support any AccessibleAction. + */ + +import java.awt.AWTException; +import java.awt.BorderLayout; +import java.awt.Container; +import java.awt.Dimension; +import java.awt.Robot; +import java.lang.reflect.InvocationTargetException; +import javax.accessibility.Accessible; +import javax.accessibility.AccessibleAction; +import javax.accessibility.AccessibleContext; +import javax.accessibility.AccessibleTable; +import javax.swing.JFrame; +import javax.swing.JScrollPane; +import javax.swing.JTable; +import javax.swing.SwingUtilities; +import javax.swing.table.DefaultTableModel; +import javax.swing.table.TableCellRenderer; + +public class BooleanRendererHasAccessibleActionTest { + private volatile JFrame frame; + private volatile JTable table; + + public static void main(String[] args) throws InterruptedException, + InvocationTargetException, AWTException { + final BooleanRendererHasAccessibleActionTest test = + new BooleanRendererHasAccessibleActionTest(); + + try { + SwingUtilities.invokeAndWait(new Runnable() { + @Override + public void run() { + test.createGUI(); + } + }); + Robot robot = new Robot(); + robot.waitForIdle(); + + SwingUtilities.invokeAndWait(new Runnable() { + @Override + public void run() { + test.runTest(); + } + }); + } finally { + SwingUtilities.invokeAndWait(new Runnable() { + @Override + public void run() { + test.dispose(); + } + }); + } + } + + private void createGUI() { + frame = new JFrame("BooleanRendererHasAccessibleActionTest"); + frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); + Container content = frame.getContentPane(); + content.setLayout(new BorderLayout()); + + String[] tblColNames = {"Column 1", "Column 2", "Column 3"}; + Object[][] tblData = { + {Boolean.TRUE, "Text 1", Boolean.FALSE}, + {Boolean.FALSE, "Text 2", Boolean.TRUE} + }; + final DefaultTableModel tblModel = new DefaultTableModel( + tblData, tblColNames) { + @Override + public Class getColumnClass(int column) { + return getValueAt(0, column).getClass(); + } + }; + table = new JTable(tblModel); + table.setPreferredScrollableViewportSize(new Dimension(400, 100)); + + JScrollPane tblScroller = new JScrollPane(table); + tblScroller.setHorizontalScrollBarPolicy( + JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS); + tblScroller.setVerticalScrollBarPolicy( + JScrollPane.VERTICAL_SCROLLBAR_ALWAYS + ); + content.add(tblScroller, BorderLayout.CENTER); + + frame.pack(); + frame.setVisible(true); + } + + private void dispose() { + if (frame != null) { + frame.dispose(); + frame = null; + } + } + + private void runTest() { + if (table == null) { + throw new RuntimeException("'table' should not be null"); + } + + testAccessibleActionInCellRenderer(0, 0, true); + testAccessibleActionInCellRenderer(1, 0, true); + testAccessibleActionInCellRenderer(0, 2, true); + testAccessibleActionInCellRenderer(1, 2, true); + + testAccessibleActionInCell(0, 0, true); + testAccessibleActionInCell(1, 0, true); + testAccessibleActionInCell(0, 2, true); + testAccessibleActionInCell(1, 2, true); + + System.out.println("Test passed."); + } + + private void testAccessibleActionInCellRenderer(int row, int column, + boolean shouldBeNull) { + System.out.println(String.format( + "testAccessibleActionInCellRenderer():" + + " row='%d', column='%d', shouldBeNull='%b'", + row, column, shouldBeNull)); + + TableCellRenderer cellRenderer = table.getCellRenderer(row, column); + if (!(cellRenderer instanceof Accessible)) { + throw new RuntimeException("'cellRenderer' is not Accessible"); + } + + AccessibleContext cellRendererAc = + ((Accessible) cellRenderer).getAccessibleContext(); + if (cellRendererAc == null) { + throw new RuntimeException("'cellRendererAc' should not be null"); + } + + AccessibleAction cellRendererAa = cellRendererAc.getAccessibleAction(); + if ((shouldBeNull && (cellRendererAa != null)) || + (!shouldBeNull && (cellRendererAa == null))) { + throw new RuntimeException( + "Test failed. 'cellRendererAa' is not as should be"); + } + } + + private void testAccessibleActionInCell(int row, int column, + boolean shouldBeNull) { + System.out.println(String.format("testAccessibleActionInCell():" + + " row='%d', column='%d', shouldBeNull='%b'", + row, column, shouldBeNull)); + + AccessibleContext tblAc = table.getAccessibleContext(); + AccessibleTable accessibleTbl = tblAc.getAccessibleTable(); + if (accessibleTbl == null) { + throw new RuntimeException("'accessibleTbl' should not be null"); + } + + Accessible cellAccessible = accessibleTbl.getAccessibleAt(row, column); + AccessibleContext cellAc = cellAccessible.getAccessibleContext(); + if (cellAc == null) { + throw new RuntimeException("'cellAc' should not be null"); + } + + AccessibleAction cellAa = cellAc.getAccessibleAction(); + if ((shouldBeNull && (cellAa != null)) || + (!shouldBeNull && (cellAa == null))) { + throw new RuntimeException( + "Test failed. 'cellAa' is not as should be"); + } + } +} diff --git a/test/jdk/javax/management/remote/mandatory/connection/DefaultAgentFilterTest.java b/test/jdk/javax/management/remote/mandatory/connection/DefaultAgentFilterTest.java index 1c688b2252431401f00419d0079c4f8930b26311..41028039b7835e59021a86264bbdb232324b8ca2 100644 --- a/test/jdk/javax/management/remote/mandatory/connection/DefaultAgentFilterTest.java +++ b/test/jdk/javax/management/remote/mandatory/connection/DefaultAgentFilterTest.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 @@ -43,6 +43,7 @@ import java.rmi.registry.LocateRegistry; import java.rmi.registry.Registry; import java.util.ArrayList; import java.util.Arrays; +import java.util.concurrent.TimeUnit; import java.util.HashMap; import java.util.HashSet; import java.util.List; @@ -110,17 +111,21 @@ public class DefaultAgentFilterTest { try { AtomicBoolean error = new AtomicBoolean(false); AtomicBoolean bindError = new AtomicBoolean(false); + // The predicate below tries to recognise failures. On a port clash, it sees e.g. + // Error: Exception thrown by the agent : java.rmi.server.ExportException: Port already in use: 46481; nested exception is: + // ...and will never see "main enter" from TestApp. p = ProcessTools.startProcess( TEST_APP_NAME + "{" + name + "}", pb, (line) -> { - if (line.toLowerCase().contains("exception") - || line.toLowerCase().contains("error")) { + if (line.contains("Exception")) { error.set(true); + bindError.set(line.toLowerCase().contains("port already in use")); + return true; // On Exception, app will never start } - bindError.set(line.toLowerCase().contains("bindexception")); - return true; - }); + return line.contains("main enter"); + }, + 60, TimeUnit.SECONDS); if (bindError.get()) { throw new BindException("Process could not be started"); } else if (error.get()) { @@ -164,9 +169,25 @@ public class DefaultAgentFilterTest { } private static final String TEST_APP_NAME = "TestApp"; + private static final int FREE_PORT_ATTEMPTS = 10; private static void testDefaultAgent(String propertyFile) throws Exception { - int port = Utils.getFreePort(); + for (int i = 1; i <= FREE_PORT_ATTEMPTS; i++) { + int port = Utils.getFreePort(); + System.out.println("Attempting testDefaultAgent(" + propertyFile + ") with port: " + port); + try { + testDefaultAgent(propertyFile, port); + break; // return succesfully + } catch (BindException b) { + // Retry with new port. Throw if last iteration: + if (i == FREE_PORT_ATTEMPTS) { + throw(b); + } + } + } + } + + private static void testDefaultAgent(String propertyFile, int port) throws Exception { String propFile = System.getProperty("test.src") + File.separator + propertyFile; List pbArgs = new ArrayList<>(Arrays.asList( "-cp", @@ -235,53 +256,32 @@ public class DefaultAgentFilterTest { public static void main(String[] args) throws Exception { System.out.println("---" + DefaultAgentFilterTest.class.getName() + "-main: starting ..."); - boolean retry = false; - do { - try { - // filter DefaultAgentFilterTest$MyTestObject - testDefaultAgent("mgmt1.properties"); - System.out.println("----\tTest FAILED !!"); - throw new RuntimeException("---" + DefaultAgentFilterTest.class.getName() + " - No exception reported"); - } catch (Exception ex) { - if (ex instanceof InvocationTargetException) { - if (ex.getCause() instanceof BindException - || ex.getCause() instanceof java.rmi.ConnectException) { - System.out.println("Failed to allocate ports. Retrying ..."); - retry = true; - } - } else if (ex instanceof InvalidClassException) { - System.out.println("----\tTest PASSED !!"); - } else if (ex instanceof UnmarshalException - && ((UnmarshalException) ex).getCause() instanceof InvalidClassException) { - System.out.println("----\tTest PASSED !!"); - } else { - System.out.println(ex); - System.out.println("----\tTest FAILED !!"); - throw ex; - } - } - } while (retry); - retry = false; - do { - try { - // filter non-existent class - testDefaultAgent("mgmt2.properties"); + try { + // filter DefaultAgentFilterTest$MyTestObject + testDefaultAgent("mgmt1.properties"); + System.out.println("----\tTest FAILED !!"); + throw new RuntimeException("---" + DefaultAgentFilterTest.class.getName() + " - No exception reported"); + } catch (Exception ex) { + if (ex instanceof InvalidClassException) { System.out.println("----\tTest PASSED !!"); - } catch (Exception ex) { - if (ex instanceof InvocationTargetException) { - if (ex.getCause() instanceof BindException - || ex.getCause() instanceof java.rmi.ConnectException) { - System.out.println("Failed to allocate ports. Retrying ..."); - retry = true; - } - } else { - System.out.println(ex); - System.out.println("----\tTest FAILED !!"); - throw ex; - } + } else if (ex instanceof UnmarshalException + && ((UnmarshalException) ex).getCause() instanceof InvalidClassException) { + System.out.println("----\tTest PASSED !!"); + } else { + System.out.println(ex); + System.out.println("----\tTest FAILED !!"); + throw ex; } - } while (retry); - + } + try { + // filter non-existent class + testDefaultAgent("mgmt2.properties"); + System.out.println("----\tTest PASSED !!"); + } catch (Exception ex) { + System.out.println(ex); + System.out.println("----\tTest FAILED !!"); + throw ex; + } System.out.println("---" + DefaultAgentFilterTest.class.getName() + "-main: finished ..."); } diff --git a/test/jdk/javax/net/ssl/ALPN/SSLServerSocketAlpnTest.java b/test/jdk/javax/net/ssl/ALPN/SSLServerSocketAlpnTest.java index a9373ed09f9da803f4d522b283bdcc1db5524715..2752649dc74e41e4e4fb48dd5a1430a92c113fce 100644 --- a/test/jdk/javax/net/ssl/ALPN/SSLServerSocketAlpnTest.java +++ b/test/jdk/javax/net/ssl/ALPN/SSLServerSocketAlpnTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2016, 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 @@ -484,7 +484,7 @@ public class SSLServerSocketAlpnTest { */ if ((local != null) && (remote != null)) { // If both failed, return the curthread's exception. - local.initCause(remote); + local.addSuppressed(remote); exception = local; } else if (local != null) { exception = local; diff --git a/test/jdk/javax/net/ssl/ALPN/SSLSocketAlpnTest.java b/test/jdk/javax/net/ssl/ALPN/SSLSocketAlpnTest.java index ef72474f4177e35dce3844b79ce2ed8b6f3f9151..172eecd46089b7c035b2d8baa21efa1468a80d4d 100644 --- a/test/jdk/javax/net/ssl/ALPN/SSLSocketAlpnTest.java +++ b/test/jdk/javax/net/ssl/ALPN/SSLSocketAlpnTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2016, 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 @@ -480,7 +480,7 @@ public class SSLSocketAlpnTest { */ if ((local != null) && (remote != null)) { // If both failed, return the curthread's exception. - local.initCause(remote); + local.addSuppressed(remote); exception = local; } else if (local != null) { exception = local; diff --git a/test/jdk/javax/net/ssl/DTLS/CipherSuite.java b/test/jdk/javax/net/ssl/DTLS/CipherSuite.java index 773fb08d3176e05f8ddb247e4fb619e19d7648e1..1c4b1c6d84f0269d1410e2e3c4308e969ff6cd5f 100644 --- a/test/jdk/javax/net/ssl/DTLS/CipherSuite.java +++ b/test/jdk/javax/net/ssl/DTLS/CipherSuite.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 @@ -51,6 +51,9 @@ import javax.net.ssl.SSLEngine; import java.security.Security; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; /** * Test common DTLS cipher suites. @@ -59,10 +62,12 @@ public class CipherSuite extends DTLSOverDatagram { // use the specific cipher suite volatile static String cipherSuite; + private static boolean reenable; public static void main(String[] args) throws Exception { if (args.length > 1 && "re-enable".equals(args[1])) { Security.setProperty("jdk.tls.disabledAlgorithms", ""); + reenable = true; } cipherSuite = args[0]; @@ -77,6 +82,11 @@ public class CipherSuite extends DTLSOverDatagram { if (isClient) { engine.setEnabledCipherSuites(new String[]{cipherSuite}); + } else if (reenable) { + List cipherSuites = + new ArrayList(Arrays.asList(engine.getEnabledCipherSuites())); + cipherSuites.add(cipherSuite); + engine.setEnabledCipherSuites(cipherSuites.toArray(new String[0])); } return engine; diff --git a/test/jdk/javax/net/ssl/DTLS/DTLSSignatureSchemes.java b/test/jdk/javax/net/ssl/DTLS/DTLSSignatureSchemes.java new file mode 100644 index 0000000000000000000000000000000000000000..5dd897b1bd7d1b8afd35acf58c8224256ee7a983 --- /dev/null +++ b/test/jdk/javax/net/ssl/DTLS/DTLSSignatureSchemes.java @@ -0,0 +1,137 @@ +/* + * 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 8280494 + * @summary (D)TLS signature schemes + * @modules java.base/sun.security.util + * @library /test/lib + * @build DTLSOverDatagram + * @run main/othervm DTLSSignatureSchemes + */ + +import javax.net.ssl.SSLEngine; +import javax.net.ssl.SSLParameters; +import java.security.Security; + +/** + * Test DTLS client authentication. + */ +public class DTLSSignatureSchemes extends DTLSOverDatagram { + private final String[] serverSignatureSchemes; + private final String[] clientSignatureSchemes; + + public DTLSSignatureSchemes(String[] serverSignatureSchemes, + String[] clientSignatureSchemes) { + this.serverSignatureSchemes = serverSignatureSchemes; + this.clientSignatureSchemes = clientSignatureSchemes; + } + + @Override + SSLEngine createSSLEngine(boolean isClient) throws Exception { + SSLEngine engine = super.createSSLEngine(isClient); + + SSLParameters sslParameters = engine.getSSLParameters(); + if (isClient) { + sslParameters.setSignatureSchemes(clientSignatureSchemes); + } else { + sslParameters.setSignatureSchemes(serverSignatureSchemes); + } + engine.setSSLParameters(sslParameters); + + return engine; + } + + public static void main(String[] args) throws Exception { + Security.setProperty("jdk.tls.disabledAlgorithms", ""); + + runTest(new String[] { + "ecdsa_secp256r1_sha256", + "ed25519" + }, + new String[] { + "ecdsa_secp256r1_sha256", + "ed25519" + }, + false); + runTest(new String[] { + "ecdsa_secp256r1_sha256" + }, + new String[] { + "ecdsa_secp256r1_sha256" + }, + false); + runTest(null, + new String[] { + "ecdsa_secp256r1_sha256" + }, + false); + runTest(new String[] { + "ecdsa_secp256r1_sha256" + }, + null, + false); + runTest(new String[0], + new String[] { + "ecdsa_secp256r1_sha256" + }, + true); + runTest(new String[] { + "ecdsa_secp256r1_sha256" + }, + new String[0], + true); + runTest(new String[] { + "ecdsa_secp256r1_shaNA" + }, + new String[] { + "ecdsa_secp256r1_sha256" + }, + true); + } + + private static void runTest(String[] serverSignatureSchemes, + String[] clientSignatureSchemes, + boolean exceptionExpected) throws Exception { + DTLSSignatureSchemes testCase = new DTLSSignatureSchemes( + serverSignatureSchemes, clientSignatureSchemes); + 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/SSLException/CheckSSLHandshakeException.java b/test/jdk/javax/net/ssl/SSLException/CheckSSLHandshakeException.java new file mode 100644 index 0000000000000000000000000000000000000000..4c8aba3de44d0e24d02bd771d47fc6f9474ada54 --- /dev/null +++ b/test/jdk/javax/net/ssl/SSLException/CheckSSLHandshakeException.java @@ -0,0 +1,50 @@ +/* + * 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 8282723 + * @summary Add constructors taking a cause to JSSE exceptions + */ +import javax.net.ssl.SSLHandshakeException; +import java.util.Objects; + +public class CheckSSLHandshakeException { + private static String exceptionMessage = "message"; + private static Throwable exceptionCause = new RuntimeException(); + + public static void main(String[] args) throws Exception { + testException( + new SSLHandshakeException(exceptionMessage, exceptionCause)); + } + + private static void testException(Exception ex) { + if (!Objects.equals(ex.getMessage(), exceptionMessage)) { + throw new RuntimeException("Unexpected exception message"); + } + + if (ex.getCause() != exceptionCause) { + throw new RuntimeException("Unexpected exception cause"); + } + } +} diff --git a/src/hotspot/share/gc/shared/cardGeneration.inline.hpp b/test/jdk/javax/net/ssl/SSLException/CheckSSLKeyException.java similarity index 52% rename from src/hotspot/share/gc/shared/cardGeneration.inline.hpp rename to test/jdk/javax/net/ssl/SSLException/CheckSSLKeyException.java index bd8285af679de0b6640abee295b683562e2d079d..dcd62fcf8e7d367504e2b43a6a34ad720d0f40ec 100644 --- a/src/hotspot/share/gc/shared/cardGeneration.inline.hpp +++ b/test/jdk/javax/net/ssl/SSLException/CheckSSLKeyException.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2019, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -19,38 +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_GC_SHARED_CARDGENERATION_INLINE_HPP -#define SHARE_GC_SHARED_CARDGENERATION_INLINE_HPP - -#include "gc/shared/cardGeneration.hpp" - -#include "gc/shared/space.hpp" - -inline size_t CardGeneration::capacity() const { - return space()->capacity(); -} - -inline size_t CardGeneration::used() const { - return space()->used(); -} - -inline size_t CardGeneration::free() const { - return space()->free(); -} - -inline MemRegion CardGeneration::used_region() const { - return space()->used_region(); -} - -inline bool CardGeneration::is_in(const void* p) const { - return space()->is_in(p); -} - -inline CompactibleSpace* CardGeneration::first_compaction_space() const { - return space(); +/* + * @test + * @bug 8282723 + * @summary Add constructors taking a cause to JSSE exceptions + */ +import javax.net.ssl.SSLKeyException; +import java.util.Objects; + +public class CheckSSLKeyException { + private static String exceptionMessage = "message"; + private static Throwable exceptionCause = new RuntimeException(); + + public static void main(String[] args) throws Exception { + testException( + new SSLKeyException(exceptionMessage, exceptionCause)); + } + + private static void testException(Exception ex) { + if (!Objects.equals(ex.getMessage(), exceptionMessage)) { + throw new RuntimeException("Unexpected exception message"); + } + + if (ex.getCause() != exceptionCause) { + throw new RuntimeException("Unexpected exception cause"); + } + } } - -#endif // SHARE_GC_SHARED_CARDGENERATION_INLINE_HPP diff --git a/test/jdk/javax/net/ssl/SSLException/CheckSSLPeerUnverifiedException.java b/test/jdk/javax/net/ssl/SSLException/CheckSSLPeerUnverifiedException.java new file mode 100644 index 0000000000000000000000000000000000000000..04184e99306bc7838bdbdad8cf5a021f75b36752 --- /dev/null +++ b/test/jdk/javax/net/ssl/SSLException/CheckSSLPeerUnverifiedException.java @@ -0,0 +1,50 @@ +/* + * 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 8282723 + * @summary Add constructors taking a cause to JSSE exceptions + */ +import javax.net.ssl.SSLPeerUnverifiedException; +import java.util.Objects; + +public class CheckSSLPeerUnverifiedException { + private static String exceptionMessage = "message"; + private static Throwable exceptionCause = new RuntimeException(); + + public static void main(String[] args) throws Exception { + testException( + new SSLPeerUnverifiedException(exceptionMessage, exceptionCause)); + } + + private static void testException(Exception ex) { + if (!Objects.equals(ex.getMessage(), exceptionMessage)) { + throw new RuntimeException("Unexpected exception message"); + } + + if (ex.getCause() != exceptionCause) { + throw new RuntimeException("Unexpected exception cause"); + } + } +} diff --git a/test/jdk/javax/net/ssl/SSLException/CheckSSLProtocolException.java b/test/jdk/javax/net/ssl/SSLException/CheckSSLProtocolException.java new file mode 100644 index 0000000000000000000000000000000000000000..3f62fac8f771bba2521155b22975d2510fee3fe2 --- /dev/null +++ b/test/jdk/javax/net/ssl/SSLException/CheckSSLProtocolException.java @@ -0,0 +1,50 @@ +/* + * 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 8282723 + * @summary Add constructors taking a cause to JSSE exceptions + */ +import javax.net.ssl.SSLProtocolException; +import java.util.Objects; + +public class CheckSSLProtocolException { + private static String exceptionMessage = "message"; + private static Throwable exceptionCause = new RuntimeException(); + + public static void main(String[] args) throws Exception { + testException( + new SSLProtocolException(exceptionMessage, exceptionCause)); + } + + private static void testException(Exception ex) { + if (!Objects.equals(ex.getMessage(), exceptionMessage)) { + throw new RuntimeException("Unexpected exception message"); + } + + if (ex.getCause() != exceptionCause) { + throw new RuntimeException("Unexpected exception cause"); + } + } +} diff --git a/test/jdk/javax/net/ssl/SSLParameters/SignatureSchemes.java b/test/jdk/javax/net/ssl/SSLParameters/SignatureSchemes.java new file mode 100644 index 0000000000000000000000000000000000000000..7dadeff5703138593b7603a78b2020c3e87e03ee --- /dev/null +++ b/test/jdk/javax/net/ssl/SSLParameters/SignatureSchemes.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 8280494 + * @summary (D)TLS signature schemes + * @library /javax/net/ssl/templates + * @run main/othervm SignatureSchemes + */ + +import javax.net.ssl.SSLParameters; +import javax.net.ssl.SSLServerSocket; +import javax.net.ssl.SSLSocket; +import java.security.Security; + +public class SignatureSchemes extends SSLSocketTemplate { + private final String[] serverSignatureSchemes; + private final String[] clientSignatureSchemes; + private final boolean exceptionExpected; + + public SignatureSchemes(String[] serverSignatureSchemes, + String[] clientSignatureSchemes, + boolean exceptionExpected) { + this.serverSignatureSchemes = serverSignatureSchemes; + this.clientSignatureSchemes = clientSignatureSchemes; + this.exceptionExpected = exceptionExpected; + } + + @Override + protected void configureServerSocket(SSLServerSocket sslServerSocket) { + SSLParameters sslParameters = sslServerSocket.getSSLParameters(); + sslParameters.setSignatureSchemes(serverSignatureSchemes); + sslServerSocket.setSSLParameters(sslParameters); + } + + @Override + protected void configureClientSocket(SSLSocket socket) { + SSLParameters sslParameters = socket.getSSLParameters(); + sslParameters.setSignatureSchemes(clientSignatureSchemes); + socket.setSSLParameters(sslParameters); + } + + @Override + protected void runServerApplication(SSLSocket socket) throws Exception { + 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[] { + "ecdsa_secp256r1_sha256", + "ed25519" + }, + new String[] { + "ecdsa_secp256r1_sha256", + "ed25519" + }, + false); + runTest(new String[] { + "ecdsa_secp256r1_sha256" + }, + new String[] { + "ecdsa_secp256r1_sha256" + }, + false); + runTest(null, + new String[] { + "ecdsa_secp256r1_sha256" + }, + false); + runTest(new String[] { + "ecdsa_secp256r1_sha256" + }, + null, + false); + runTest(new String[0], + new String[] { + "ecdsa_secp256r1_sha256" + }, + true); + runTest(new String[] { + "ecdsa_secp256r1_sha256" + }, + new String[0], + true); + runTest(new String[] { + "ecdsa_secp256r1_shaNA" + }, + new String[] { + "ecdsa_secp256r1_sha256" + }, + true); + } + + private static void runTest(String[] serverSignatureSchemes, + String[] clientSignatureSchemes, + boolean exceptionExpected) throws Exception { + new SignatureSchemes(serverSignatureSchemes, + clientSignatureSchemes, exceptionExpected).run(); + } +} diff --git a/test/jdk/javax/net/ssl/ServerName/EndingDotHostname.java b/test/jdk/javax/net/ssl/ServerName/EndingDotHostname.java index 20ebc144088767036b1a1913eec91f886c2d5276..bac110aa0338bd295911c33d9b0df947787bb3ca 100644 --- a/test/jdk/javax/net/ssl/ServerName/EndingDotHostname.java +++ b/test/jdk/javax/net/ssl/ServerName/EndingDotHostname.java @@ -23,14 +23,14 @@ /** * @test - * @bug 8806542 + * @bug 8065422 * @summary Trailing dot in hostname causes TLS handshake to fail * @library /javax/net/ssl/templates - * @run main/othervm -Djdk.net.hosts.file=hostsForExample EndingDotHostname + * @run main/othervm --add-opens java.base/sun.security.ssl=ALL-UNNAMED + * -Djdk.net.hosts.file=hostsForExample EndingDotHostname */ import javax.net.ssl.*; -import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.*; diff --git a/test/jdk/javax/net/ssl/ServerName/SSLSocketExplorer.java b/test/jdk/javax/net/ssl/ServerName/SSLSocketExplorer.java index 4992553eba93b95329a73cc30d3f1b5f4e2987c3..3ae2e777810f7a584b47d837cd682ee52753625d 100644 --- a/test/jdk/javax/net/ssl/ServerName/SSLSocketExplorer.java +++ b/test/jdk/javax/net/ssl/ServerName/SSLSocketExplorer.java @@ -134,7 +134,7 @@ public class SSLSocketExplorer { position += n; } - capabilities = SSLExplorer.explore(buffer, 0, recordLength);; + capabilities = SSLExplorer.explore(buffer, 0, recordLength); if (capabilities != null) { System.out.println("Record version: " + capabilities.getRecordVersion()); diff --git a/test/jdk/javax/net/ssl/ServerName/SSLSocketExplorerFailure.java b/test/jdk/javax/net/ssl/ServerName/SSLSocketExplorerFailure.java index 00d00001d871c4e8059d76277a029497fc059675..7193fcaf136fbb830b088157b012d3fd877c718c 100644 --- a/test/jdk/javax/net/ssl/ServerName/SSLSocketExplorerFailure.java +++ b/test/jdk/javax/net/ssl/ServerName/SSLSocketExplorerFailure.java @@ -135,7 +135,7 @@ public class SSLSocketExplorerFailure { position += n; } - capabilities = SSLExplorer.explore(buffer, 0, recordLength);; + capabilities = SSLExplorer.explore(buffer, 0, recordLength); if (capabilities != null) { System.out.println("Record version: " + capabilities.getRecordVersion()); diff --git a/test/jdk/javax/net/ssl/ServerName/SSLSocketExplorerMatchedSNI.java b/test/jdk/javax/net/ssl/ServerName/SSLSocketExplorerMatchedSNI.java index 724a37e1a80d2f25d931da15d54c1101e7098a97..0cea7323b8373eb8f505c2d935e3e878d5570555 100644 --- a/test/jdk/javax/net/ssl/ServerName/SSLSocketExplorerMatchedSNI.java +++ b/test/jdk/javax/net/ssl/ServerName/SSLSocketExplorerMatchedSNI.java @@ -138,7 +138,7 @@ public class SSLSocketExplorerMatchedSNI { position += n; } - capabilities = SSLExplorer.explore(buffer, 0, recordLength);; + capabilities = SSLExplorer.explore(buffer, 0, recordLength); if (capabilities != null) { System.out.println("Record version: " + capabilities.getRecordVersion()); diff --git a/test/jdk/javax/net/ssl/ServerName/SSLSocketExplorerUnmatchedSNI.java b/test/jdk/javax/net/ssl/ServerName/SSLSocketExplorerUnmatchedSNI.java index 732e0cf3097566a4d367937f9a738c9af8f0e4b1..619a997eda293191bdce8719b0d5b596a877ef68 100644 --- a/test/jdk/javax/net/ssl/ServerName/SSLSocketExplorerUnmatchedSNI.java +++ b/test/jdk/javax/net/ssl/ServerName/SSLSocketExplorerUnmatchedSNI.java @@ -130,7 +130,7 @@ public class SSLSocketExplorerUnmatchedSNI { position += n; } - capabilities = SSLExplorer.explore(buffer, 0, recordLength);; + capabilities = SSLExplorer.explore(buffer, 0, recordLength); if (capabilities != null) { System.out.println("Record version: " + capabilities.getRecordVersion()); diff --git a/test/jdk/javax/net/ssl/ServerName/SSLSocketExplorerWithCliSNI.java b/test/jdk/javax/net/ssl/ServerName/SSLSocketExplorerWithCliSNI.java index 8f2b78168649e6bf702e39947e553289b2ae6d3a..8451b44f0bf00e6633bfae3fe40503ccfa477a55 100644 --- a/test/jdk/javax/net/ssl/ServerName/SSLSocketExplorerWithCliSNI.java +++ b/test/jdk/javax/net/ssl/ServerName/SSLSocketExplorerWithCliSNI.java @@ -129,7 +129,7 @@ public class SSLSocketExplorerWithCliSNI { position += n; } - capabilities = SSLExplorer.explore(buffer, 0, recordLength);; + capabilities = SSLExplorer.explore(buffer, 0, recordLength); if (capabilities != null) { System.out.println("Record version: " + capabilities.getRecordVersion()); diff --git a/test/jdk/javax/net/ssl/ServerName/SSLSocketExplorerWithSrvSNI.java b/test/jdk/javax/net/ssl/ServerName/SSLSocketExplorerWithSrvSNI.java index f026f32e781a2787f24b9f979c7af755546b25dd..8b891e804e44f94bb23c87d28ec987ed98670fd0 100644 --- a/test/jdk/javax/net/ssl/ServerName/SSLSocketExplorerWithSrvSNI.java +++ b/test/jdk/javax/net/ssl/ServerName/SSLSocketExplorerWithSrvSNI.java @@ -129,7 +129,7 @@ public class SSLSocketExplorerWithSrvSNI { position += n; } - capabilities = SSLExplorer.explore(buffer, 0, recordLength);; + capabilities = SSLExplorer.explore(buffer, 0, recordLength); if (capabilities != null) { System.out.println("Record version: " + capabilities.getRecordVersion()); diff --git a/test/jdk/javax/net/ssl/ciphersuites/DisabledAlgorithms.java b/test/jdk/javax/net/ssl/ciphersuites/DisabledAlgorithms.java index 7bb3e2c8d2b50e37262fd0ee2bac37a14e3957a0..441f6bdff483bd5ffb77f2685db64ab02b044a89 100644 --- a/test/jdk/javax/net/ssl/ciphersuites/DisabledAlgorithms.java +++ b/test/jdk/javax/net/ssl/ciphersuites/DisabledAlgorithms.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2018, 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 @@ -23,7 +23,7 @@ /* * @test - * @bug 8076221 8211883 + * @bug 8076221 8211883 8163327 * @summary Check if weak cipher suites are disabled * @modules jdk.crypto.ec * @run main/othervm DisabledAlgorithms default @@ -60,9 +60,10 @@ public class DisabledAlgorithms { System.getProperty("test.src", "./") + "/" + pathToStores + "/" + trustStoreFile; - // supported RC4, NULL, and anon cipher suites + // supported 3DES, DES, RC4, NULL, and anon cipher suites // it does not contain KRB5 cipher suites because they need a KDC - private static final String[] rc4_null_anon_ciphersuites = new String[] { + private static final String[] desede_des_rc4_null_anon_ciphersuites + = new String[] { "TLS_ECDHE_ECDSA_WITH_RC4_128_SHA", "TLS_ECDHE_RSA_WITH_RC4_128_SHA", "SSL_RSA_WITH_RC4_128_SHA", @@ -90,11 +91,25 @@ public class DisabledAlgorithms { "TLS_DH_anon_WITH_AES_256_CBC_SHA", "TLS_DH_anon_WITH_AES_256_CBC_SHA256", "TLS_DH_anon_WITH_AES_256_GCM_SHA384", + "SSL_RSA_WITH_DES_CBC_SHA", + "SSL_DHE_RSA_WITH_DES_CBC_SHA", + "SSL_DHE_DSS_WITH_DES_CBC_SHA", + "SSL_RSA_EXPORT_WITH_DES40_CBC_SHA", + "SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA", + "SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA", + "SSL_RSA_EXPORT_WITH_RC4_40_MD5", "TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA", "TLS_ECDH_anon_WITH_AES_128_CBC_SHA", "TLS_ECDH_anon_WITH_AES_256_CBC_SHA", "TLS_ECDH_anon_WITH_NULL_SHA", - "TLS_ECDH_anon_WITH_RC4_128_SHA" + "TLS_ECDH_anon_WITH_RC4_128_SHA", + "TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA", + "TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA", + "SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA", + "SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA", + "TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA", + "TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA", + "SSL_RSA_WITH_3DES_EDE_CBC_SHA" }; public static void main(String[] args) throws Exception { @@ -113,19 +128,25 @@ public class DisabledAlgorithms { System.out.println("jdk.tls.disabledAlgorithms = " + Security.getProperty("jdk.tls.disabledAlgorithms")); - // check if RC4, NULL, and anon cipher suites + // check if 3DES, DES, RC4, NULL, and anon cipher suites // can't be used by default - checkFailure(rc4_null_anon_ciphersuites); + checkFailure(desede_des_rc4_null_anon_ciphersuites); break; case "empty": // reset jdk.tls.disabledAlgorithms Security.setProperty("jdk.tls.disabledAlgorithms", ""); System.out.println("jdk.tls.disabledAlgorithms = " + Security.getProperty("jdk.tls.disabledAlgorithms")); - - // check if RC4, NULL, and anon cipher suites can be used - // if jdk.tls.disabledAlgorithms is empty - checkSuccess(rc4_null_anon_ciphersuites); + // reset jdk.certpath.disabledAlgorithms. This is necessary + // to allow the RSA_EXPORT suites to pass which use an RSA 512 + // bit key which violates the default certpath constraints. + Security.setProperty("jdk.certpath.disabledAlgorithms", ""); + System.out.println("jdk.certpath.disabledAlgorithms = " + + Security.getProperty("jdk.certpath.disabledAlgorithms")); + + // check if 3DES, DES, RC4, NULL, and anon cipher suites + // can be used if jdk.{tls,certpath}.disabledAlgorithms is empty + checkSuccess(desede_des_rc4_null_anon_ciphersuites); break; default: throw new RuntimeException("Wrong parameter: " + args[0]); diff --git a/test/jdk/javax/net/ssl/templates/SSLExampleCert.java b/test/jdk/javax/net/ssl/templates/SSLExampleCert.java index bc8a1fdb2e9046896f493121635d47db45a77cd8..0b82aed3b7bd841c6f86b7caf481fa2e6f5b1be8 100644 --- a/test/jdk/javax/net/ssl/templates/SSLExampleCert.java +++ b/test/jdk/javax/net/ssl/templates/SSLExampleCert.java @@ -21,209 +21,249 @@ * questions. */ -import javax.net.ssl.KeyManagerFactory; -import javax.net.ssl.SSLContext; -import javax.net.ssl.TrustManagerFactory; +import javax.net.ssl.*; import java.io.*; +import java.lang.reflect.Field; import java.net.InetAddress; import java.security.KeyFactory; import java.security.KeyStore; import java.security.PrivateKey; import java.security.cert.Certificate; import java.security.cert.CertificateFactory; +import java.security.cert.PKIXBuilderParameters; import java.security.spec.PKCS8EncodedKeySpec; +import java.text.DateFormat; +import java.text.SimpleDateFormat; import java.util.Base64; +import java.util.Date; -// A template to use "www.example.com" as the server name. The caller should -// set a virtual hosts file with System Property, "jdk.net.hosts.file". This -// class will map the loopback address to "www.example.com", and write to -// the specified hosts file. +/** + * A template to use "www.example.com" as the server name. The caller should + * set a virtual hosts file with System Property, "jdk.net.hosts.file". This + * class will map the loopback address to "www.example.com", and write to + * the specified hosts file. + * + * Commands used: + * # Root CA + * > openssl req -new -config openssl.cnf -out root-ca.csr \ + * -keyout private/root-ca.key -days 7300 -newkey rsa:2048 + * > openssl ca -selfsign -config openssl.cnf -in root-ca.csr \ + * -out certs/root-ca.crt -extensions v3_ca + * -keyfile private/root-ca.key -days 7300 + * + * # www.example.com + * > openssl req -new -keyout private/example.key \ + * -out example.csr -days 7299 -newkey rsa:2048 + * > openssl ca -config openssl.cnf -in example.csr \ + * -out certs/example.crt -extensions usr_cert + * -keyfile private/root-ca.key -days 7299 + * + * # Client + * > openssl req -new -keyout private/client.key \ + * -out client.csr -days 7299 -newkey rsa:2048 + * > openssl ca -config openssl.cnf -in client.csr \ + * -out certs/client.crt -extensions usr_cert + * -keyfile private/root-ca.key -days 7299 + * + * The key files should be in PKCS8 format: + * > openssl pkcs8 -topk8 -inform PEM -outform pem \ + * -in private/example.key -out private/example-pkcs.key -nocrypt + */ public enum SSLExampleCert { // Version: 3 (0x2) - // Serial Number: 15223159159760931473 (0xd34386999cc8ca91) + // Serial Number: 4097 (0x1001) // Signature Algorithm: sha256WithRSAEncryption - // Issuer: C=US, ST=California, O=Example, OU=Test + // Issuer: C = US, ST = California, O = Example, OU = Test // Validity - // Not Before: Jan 26 04:50:29 2022 GMT - // Not After : Feb 25 04:50:29 2022 GMT - // Subject: C=US, ST=California, O=Example, OU=Test - // Public Key Algorithm: rsaEncryption + // Not Before: Feb 25 20:12:04 2022 GMT + // Not After : Feb 20 20:12:04 2042 GMT + // Subject: C = US, ST = California, O = Example, OU = Test + // Subject Public Key Info: + // Public Key Algorithm: rsaEncryption + // RSA Public-Key: (2048 bit) CA_RSA("RSA", - """ + """ -----BEGIN CERTIFICATE----- - MIIDXDCCAkSgAwIBAgIJANNDhpmcyMqRMA0GCSqGSIb3DQEBCwUAMEMxCzAJBgNV - BAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRAwDgYDVQQKDAdFeGFtcGxlMQ0w - CwYDVQQLDARUZXN0MB4XDTIyMDEyNjA0NTAyOVoXDTIyMDIyNTA0NTAyOVowQzEL - MAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWExEDAOBgNVBAoMB0V4YW1w - bGUxDTALBgNVBAsMBFRlc3QwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB - AQDnOL2hB/GYyYziXo/ppxi7V1LfMMLeHt0lZbYlrmNxUlln4naI4B4Lkg75eb1Y - DgC7MZQd5nKijK9Dkq52Z2zLxaqBYnLxKJ36qKPqbtTL3I8mfUvVEeNIDN/8YTAt - suIEQi54dNtQVrB4YReMdnUq+xCKLAfEio4QLEQr7KtyCBXHZpM7RYRT0giQFvDU - 2kls9lFLeqKXgocnA7VpoL0V12hpxDeJoRm1szf0M5YXGJumQLaE5qM/+P2OOhw/ - T+xkupy2GF02s6FBXkH7NrFIjtuBSaVhSvCG/N7njWSn339thr3kiPEaCS4KSH5E - E6FEazxZQrTCbkQQ+v3y1pS1AgMBAAGjUzBRMA8GA1UdEwEB/wQFMAMBAf8wHQYD - VR0OBBYEFMFw2FWUvwZx3FJjm1G9TujCjAJSMB8GA1UdIwQYMBaAFMFw2FWUvwZx - 3FJjm1G9TujCjAJSMA0GCSqGSIb3DQEBCwUAA4IBAQCJsJjeYcT/GtKp64C+9KCi - Vgw/WnBZwbosSFZmqyID8aAnAxaGMkZ2B2pUZHTtCkBf6d9c0tuWb5yF8npV77sE - bZqeNg2GU7EvH3WPgPbQVT7+Qb+WbY3EEPgJHLytch61Rm/TRQ3OqD0B+Gs7YjAU - fEspmk1JJ6DWuXX13SHoGWgVnO7rXBnCJaGnGpONtggG4oO5hrwnMzQZKh5eZDhC - 7tkNPqVDoLv+QqnFk8q6k8hhxnVf+aw56IdsebN+9Bi+Lv6OQ+stKUo/u/RTW2z1 - odCOwc8DPF3jbacJsOmLhl3ciuWGOckx9KCvaBeTTgkPdLQH1gpNha2tnqgxUXmC + MIIDtDCCApygAwIBAgICEAEwDQYJKoZIhvcNAQELBQAwQzELMAkGA1UEBhMCVVMx + EzARBgNVBAgTCkNhbGlmb3JuaWExEDAOBgNVBAoTB0V4YW1wbGUxDTALBgNVBAsT + BFRlc3QwHhcNMjIwMjI1MjAxMjA0WhcNNDIwMjIwMjAxMjA0WjBDMQswCQYDVQQG + EwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEQMA4GA1UEChMHRXhhbXBsZTENMAsG + A1UECxMEVGVzdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKOGhEDj + lZ5R6o20kJdgrIRcY1he4qKLWQ4vU0thqAg4mEcKCZZn4/NL05UgJCFLwYaxMZZe + etb/WaTRvQpDDFh7AhsMR24m6zKKJVk9E/e/8ur7sGDIVq8hZOBTq85ZdxPj/zKW + wB1BR/RcY4DsGno1USlkV7TVeZc1qpJHTPImesevzH7zX8nhnFlf4TTQbpQt6RxU + cr+udWpMOyP9xMerIyp7jpPy79tIaGP2x7ryt2BB9FU4RwPk4DcdfOkmdS86md1c + GI9H5qM5rUzyqey0J8wMRLj+E0Vx0F1XELZeTtyulbIbhrBhu/KOXZG2zNIeK+2F + XxDlx9tD+bbcJfUCAwEAAaOBsTCBrjAdBgNVHQ4EFgQULjM9fwJnC3Tp1QYM8HNL + y60btl0wbAYDVR0jBGUwY4AULjM9fwJnC3Tp1QYM8HNLy60btl2hR6RFMEMxCzAJ + BgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMRAwDgYDVQQKEwdFeGFtcGxl + MQ0wCwYDVQQLEwRUZXN0ggIQATAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQE + AwIBBjANBgkqhkiG9w0BAQsFAAOCAQEAR0Mk+2X/rr4kYYfHsQUIsROwDZSQhQr3 + QOeLc7fyTjkM96OHXN2dKVoOcpzgKi1goHW7lh8vVmKRQk2wfFqRZV9/kQBFK/gz + QtN5gp+pA8Wk912Uj5gD0loiPcRf5bDElvLnr2iwt4VdKkvGIYa9Eu9CYbkf1x3t + ahVLmrZLBkqvKxo4MG4KGYXkqtII3M6clM4ScFa/0rR1nGZOgZyqG7AMMHc01csA + oLlEZx2hUcpJbz+sfCGUWYaF2uKJvuWMNFbGSDhfs8pOMGgelMOHaKVtgOEfEASN + TSqzqn0vzjJ78Mi6mN7/6L/onDKzROxClw0hc6L+PIhIHftD1ckvVQ== -----END CERTIFICATE-----""", - """ - MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQDnOL2hB/GYyYzi - Xo/ppxi7V1LfMMLeHt0lZbYlrmNxUlln4naI4B4Lkg75eb1YDgC7MZQd5nKijK9D - kq52Z2zLxaqBYnLxKJ36qKPqbtTL3I8mfUvVEeNIDN/8YTAtsuIEQi54dNtQVrB4 - YReMdnUq+xCKLAfEio4QLEQr7KtyCBXHZpM7RYRT0giQFvDU2kls9lFLeqKXgocn - A7VpoL0V12hpxDeJoRm1szf0M5YXGJumQLaE5qM/+P2OOhw/T+xkupy2GF02s6FB - XkH7NrFIjtuBSaVhSvCG/N7njWSn339thr3kiPEaCS4KSH5EE6FEazxZQrTCbkQQ - +v3y1pS1AgMBAAECggEBAJQAKLkTWZx/njMjbiCT+Wuo6H2+O21r+ge/BAk4h6R4 - nou1VEQmmHS1h+o992mOhP9NK867vDK5tFGfaRaW+vevzYTF3GbqpbxVB56+VG0s - /2AWoVx/96gdvZ1RJEKMFsm9BvvJaLwS0SAsnaMmC7d4Ps0Cg/JU8bv+aaBn/BGf - TWiofYWeUk6llco4kO9H2APxUVzlaUUU/cPAJqX7XktnhDCI9/esuVg7nVR0XxOF - GDrV/jdqSYmSbp4aTRXgI9nwxOmlKiGgevTrCUXl3/KaJxZekllVjushY1VVzgbY - K5R4bcN5MXMmFdgF9DTEW72RqEfg9iXqyhYbZp3Q/UECgYEA/yiaJd0w2HS22HSg - o4dJ072WbyR3qUqQmPbSUn9hBQTJAz1eX3cci8u4oawo/S+jN38b/DfpSg3eIMLB - vnXW3wZtodpJnFaweKd3yUaSF2r9vZRHJgfPfe67VbruEOF6BsCjTq/deGeNnGeH - /IDVn9WtSeRX/bv/s5YHvGaHGGUCgYEA5/vugmilOBq979EqksCG/7EQHSOoEukO - J/aunDyEwz+BMEHOEW7tDMUefdiSfnGXSW+ZTmpmvc+aLk37Xuo34jpugK5ayUFY - iYVgiqdnygGiBevBM2o0O/parQkAGEB8GPButrYItUzubUgXnuw+EdMiXGnpjJaK - S3dPYJEHvhECgYEAjqIIwV/LPUTJLWjMn30yBN43KLvu9ECNYiSfX6R6/I43O8tj - ZOQ1nePsutt9MkMd7xjr8OrkSxRDdnbITQqcaaGzSUW33mALV/btnCMJ6XNSklZA - C39UOuZn7D2JdQBF8V5gK81ddUAVxjeNqdXvFOEidGrj0R/1iVM10dhSbo0CgYBk - P8GtR02Gtj+4P/qW2m48VqbxALSkH2SHrpl8WMbCnVHVqcpETFxSNWjc11dPHwVS - rdBhS6fEhM9LDVYAiVTHBZs1LqN67ys0mpfCs18ts5Dx4BRohI+4D5NZzVbmJA+8 - s0IU4QtYVbt/LDVQ7yRPjZ7+sqJDp9ZxkEiUIXhoEQKBgQCPG2f8BhsCYNAOV60F - hJVjhDdf59Mia3B2J9SSnrg6Tl2rWB7GPP19TiSPFS6Sn95mWrMjZ2ZuOXtCYV4H - +hmu87AV2CXFhW5c588cajXMT92GFVMSXdE1OHRzDjhpH+/ll8SnmQa7sXmEV36+ - sawd7mwcB9IEi562wglADxBUCA== + """ + MIIFHDBOBgkqhkiG9w0BBQ0wQTApBgkqhkiG9w0BBQwwHAQIn/uWtEzLDK8CAggA + MAwGCCqGSIb3DQIJBQAwFAYIKoZIhvcNAwcECIk7+JC4ErMDBIIEyA3yvNhMm/Oj + ZdkN0HSzPyLv9bOfUyyx4NA121kizZIq/FkUjn8pGxzU63rzMk2vU1hmp2/O3ymr + vmV7gzXRp4ULZCjFwn4cLxi9ieKgBOr9MmgTlRc1oZ9P/Y8eWhmjGxA2CU3fy7Kv + DyzftqAetV8YzTelk8xqxLrGevB16O3zDbFj4dcmG7a0i75kqlI8QyQklJ9uyE10 + SELWFlV6w+3GD82YrbR/8v4fE5KP/nAPbtN4h4C7MY3kJQL+apHr5B3Jst+6N62t + JzmxGS5z3ZVT3Bn3mxi8awo8/XS8s+ZOSnH6nHvz83NBUQwSkVbtujlg+yMD2jg4 + Nt3LWfLnF8Q6n4oAQ1ZP9KJyVIh8+PN12txIRoWq1pF74hJmbfVfiCSR/tMrw6lr + XqlkG1Mi7RmpTCz9ScTUBWY/dyScYFITenv/WE+UnfQ+DXBC+78lkmL36M0Rx/ip + S4O1Tgy/z/MIv1s+ZpAFsRRczlpo9lbVEMuSGEWWTIQJCRPFV8Y1NKHmWUgeZpl3 + 2YUjpHNyQt/a1s1h1g5w9+UNuABt/3cUUnlA7psueb6l4x6M92QFBOpe1xUDL51D + RpaipVl1luFWvE84hqgCIv8Kh9EbkAlclmK8CIOkMQAabk0GmhCfEdm+PCW61Cao + rfCMwZ9Bx6zAcXGRrvl0sK35z8C3r8wLftaS/5xF6RTJBy6XY2iiFW6D44qZDFbh + 0rWV8zDtCf2+OZtEvPkeUn3sjevDW78TM6F7HBjXAeIFrNyJGVe2CTlEJLoZi5pX + W1blhMJ93N1mLiDYisILANmJRBfGMt0tYE/pGcJRlkuqG0qylnqRojjL83CTQvFy + 46q/obR36enRDvCZPvQrX2dB7Vkgpkz/drZ6+avmKdQcTjY/ycCd3DclwexhgUoX + QDntZuJQLp7C4tFfHRy2uh4DOEjzMP6a/NQ3q7p6vc6BTNTFZRUAdyNwcEDIzSLM + nZSPFBiz+gukhtNSCO28kLc8OX1hYsSAMgzbImcMtAiQHG3bFAJ0cs0jF4U9VrJt + 4/97kiDBuCgGb2b5t0+uDqipE6G4B6494IGm5KoIPAPbXMJQstmuzjTJt95UTF+p + e60AnWIXcvEOouIIMzC7gH2g23St5Bo6NixfxcmVfkFa92TDlCTxEz5Z5mnma06k + Pao4Km1eJkYS/QaCDnCZs/yCAMhINUTTDd0/7Y9YE3Dmd5B1s2wOa+ovESSL3Mdv + dZoxh91QR+6hQuz3iYztC/BszMtATH8MznAoco0QFAhKi56Wppe+p1ATLWFMqk4W + elX9vtw5XLucKy5cMkQYh144SnrerlPJTAOGy0XXKunj8ceZfEN6zcS9Us9IN5aF + iENMFHjPsscrrKFhKypaMIn67PuIhVhw4PnGrWejr6TM1gUx+zOcRCwT+5ka2L7U + aqmgS8cDg5ZfAHcbig7No9kku/OSk+5QzkVKca2TZQHm++60oQTzRl3/NWiELO+e + Sl6r8i7dS0Kv3bB/AbLfIHtDgebxUh78qXMel/OUWd58ezxBS74rZ4AQTpYcdTbR + jKHploWi8h5yXYn/YdEZG1vW/zYseFNb7QKT5Cznucl8O/+lNZIOVw63Pq368dTD + tG1GZkIlwM+jlJjRew05YQ== """), // Version: 3 (0x2) - // Serial Number: 14845986384898254166 (0xce0789f5ac256556) - // Signature Algorithm: sha1WithRSAEncryption - // Issuer: C=US, ST=California, O=Example, OU=Test + // Serial Number: 4098 (0x1002) + // Signature Algorithm: sha256WithRSAEncryption + // Issuer: C = US, ST = California, O = Example, OU = Test // Validity - // Not Before: Jan 26 04:50:29 2022 GMT - // Not After : Feb 25 04:50:29 2022 GMT - // Subject: C=US, ST=California, O=Example, OU=Test, CN=www.example.com - // Public Key Algorithm: rsaEncryption + // Not Before: Feb 25 20:31:29 2022 GMT + // Not After : Feb 19 20:31:29 2042 GMT + // Subject: C = US, ST = California, O = Example, OU = Test, CN = www.example.com + // Subject Public Key Info: + // Public Key Algorithm: rsaEncryption + // RSA Public-Key: (2048 bit) SERVER_EXAMPLE_RSA("RSA", - """ + """ -----BEGIN CERTIFICATE----- - MIIDjDCCAnSgAwIBAgIJAM4HifWsJWVWMA0GCSqGSIb3DQEBBQUAMEMxCzAJBgNV - BAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRAwDgYDVQQKDAdFeGFtcGxlMQ0w - CwYDVQQLDARUZXN0MB4XDTIyMDEyNjA0NTAyOVoXDTIyMDIyNTA0NTAyOVowXTEL - MAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWExEDAOBgNVBAoMB0V4YW1w - bGUxDTALBgNVBAsMBFRlc3QxGDAWBgNVBAMMD3d3dy5leGFtcGxlLmNvbTCCASIw - DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAK/i4bVSAF6/aFHyzrFAON8Uwn2a - Q9jFoAMowUkH6+PCexlt4wCOEMVH9IQPa1yzeVlkYRqHggz3i6aVYvd27Q+c6vOF - FuRegWdJusyEuoXd5nwxSGiZZMLmFQswODSPmucroCG+Tq9RKY5oEKiRP8tUDqyn - eE52PaeSR2Q6mng7BM5Llj7amVgimO3jlH2AWLLpHNTkc3j/M1QrLFV2PqN4dpxT - OeFuVWzpfTWJSH+9Kq4u/zBMbYl8ON7DSgJAzc2BOw8VPIYIK6JIw6IDbLn4dIQf - GikdgHKB2K6EDOc9LuX6UqQQODDFU88muAyPgpGfUQjxKZeUoTqoAFyisI0CAwEA - AaNpMGcwCQYDVR0TBAIwADAdBgNVHQ4EFgQUQqf/4nqluVMZ8huD3I5FNqLXTqAw - HwYDVR0jBBgwFoAUwXDYVZS/BnHcUmObUb1O6MKMAlIwGgYDVR0RBBMwEYIPd3d3 - LmV4YW1wbGUuY29tMA0GCSqGSIb3DQEBBQUAA4IBAQBl8FJD98fJh/0KY+3LtZDW - CQZDeBSfnpq4milrvHH+gcOCaKYlB9702tAQ6rL1c1dLz/Lpw1x7EYvO8XIwXMRc - DZghf8EJ6wMpZbLVLAQLCTggiB65XPwmhUoMvgVRVLYoXT3ozmNPt7P+ZURisqem - 0/xVVfxqmHw9Hb4DNlc7oZDgOK7IrqriaBK6Amsu3m2eThsvkwTdJfeFG3ZdV6x5 - mbaGZDMt/wgWIqyq5CZNpXPaFRH7KM4zhcoqXvFAoq9jxWOuBkJUUx5EHaxGhhPw - SMgE1yl4O+N7GJmF/WMR5zp2LGKMqJ3vwLPv6QNkUmLwB5ZLYJ8E2dpj6DjQWa7X + MIIDaTCCAlGgAwIBAgICEAIwDQYJKoZIhvcNAQELBQAwQzELMAkGA1UEBhMCVVMx + EzARBgNVBAgTCkNhbGlmb3JuaWExEDAOBgNVBAoTB0V4YW1wbGUxDTALBgNVBAsT + BFRlc3QwHhcNMjIwMjI1MjAzMTI5WhcNNDIwMjE5MjAzMTI5WjBdMQswCQYDVQQG + EwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEQMA4GA1UECgwHRXhhbXBsZTENMAsG + A1UECwwEVGVzdDEYMBYGA1UEAwwPd3d3LmV4YW1wbGUuY29tMIIBIjANBgkqhkiG + 9w0BAQEFAAOCAQ8AMIIBCgKCAQEA3crcRzecIV08Muh6kA0CuVKnPkU2bLC+6bpV + 7/iBZ4D3qMwO8Q02+gP71pPNoAQ1nsifxR4k9mBVYOjar35RVpuFmLRRVMargrxg + 4WWDfVgLMhOeCy8+Tl4Mp/yRL3nkr0MJd57RCOPcPE84J/1Crq1Luy2+hsXSj25L + VJKx2o6LE0tfwPWnufdNUHzHRuNoBR83OpqIT0uXH15THZS+0ZcQwrJMcKYe4JWl + 6oXWcsWbtTG+r7QLIRKck2IG7jjHFpE83Q6Iv2HkhctgGZofwSTZyMmJ8eClovva + WFLDaLL2WuI3NwZM//knjMyfsEWtWsILXayCn5NTT74ClQjWQQIDAQABo00wSzAJ + BgNVHRMEAjAAMB0GA1UdDgQWBBQ9nPjenO4PMLtMTBddNiIDsPywjzAfBgNVHSME + GDAWgBQuMz1/AmcLdOnVBgzwc0vLrRu2XTANBgkqhkiG9w0BAQsFAAOCAQEAVOvM + fMDOxOCkWB244cx7J+f2qZU6/1qGlJUiL0WRLRj1XEmB8AYSZEb6Os1suF8sotka + nA9Aw1SFA/wNyrSKazXNlOKo0In1mu/OjHU7n6XYVAyDmFGziYY8zTqG1h8ZPrI7 + oAkNgnNDwmwy7uCAvMj+Q4QQ0Q4YxTHV/i3X1HuEwThRgz9cJGdDRIAsimRHDSDO + 5hsIJo6VASz0ISrYMxNZQ1og+XktdNssPK616bPf+APwXXnsWSuGkIdGDU059DII + cTSsLTbWkTWDXAAQo+sfDZUrvqopCK000eoywEmPQrTf7O8oAQdRvTsyxwMvOONd + EWQ9pDW9+RC8l5DtRA== -----END CERTIFICATE-----""", - """ - MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCv4uG1UgBev2hR - 8s6xQDjfFMJ9mkPYxaADKMFJB+vjwnsZbeMAjhDFR/SED2tcs3lZZGEah4IM94um - lWL3du0PnOrzhRbkXoFnSbrMhLqF3eZ8MUhomWTC5hULMDg0j5rnK6Ahvk6vUSmO - aBCokT/LVA6sp3hOdj2nkkdkOpp4OwTOS5Y+2plYIpjt45R9gFiy6RzU5HN4/zNU - KyxVdj6jeHacUznhblVs6X01iUh/vSquLv8wTG2JfDjew0oCQM3NgTsPFTyGCCui - SMOiA2y5+HSEHxopHYBygdiuhAznPS7l+lKkEDgwxVPPJrgMj4KRn1EI8SmXlKE6 - qABcorCNAgMBAAECggEBAJb2SvfP7BVmf+lmV9V249lE/jHECFu0M8TCZDOEowiX - 0gRfdqjxRp+tRMdcXK/yM0Nwjo+wowTyK2DNc2YnIw11h4uAPcfA/ZxjgfssKNPh - Q4Rw4E826W8HACTcPEGQyEmF/ik4KFz9coeR9kpYcMLZ4MZ77xyZDA4Z1UDHs/Fg - egrd4k35fxIFOavsjNuekMIjZlyQ2xU1a11QDBrZAu/pjITXXulg4jCxLbeNOOPs - hH+Sx+jnsVV7qIBNwulzxEdpb3+NkWIMmOQK4HOSeHgjRVvSXXBPgYadMaP/Bzvx - AwJ9WeLZg7KWHE03aOc7CSMoyHfmhXx3gD8icGpSq8ECgYEA3TWGBSgny/wket+V - 65ldWjp4NOKHbLPtBdL9ygIO+1bGfLl5srCxUWHBYdcWCXKuB5ALCBu0hMY+TlwF - s/BzZmvVW7RLAEZZ3Q5HpawDlr9j8Kenm4X2Mqh0MSkmwIDRDHF8jRXAvWIzcBiS - +rPZm2CMZpznUSE4X+GrvTSCBbkCgYEAy4yJ58wNUavj/tR8KySn5ygPABFZ1Uoy - pIyabm18Oe3gCl5UulBskoN0WreTKnA4r9jGlnrgeuu5WfMK53AZKbC+YduZixW4 - QFuJBSMbFCBDt4nkhkMMR7VcV4jIqaOK7qNrs7ubGTZhsG8wj6/WWdCp3Avnx1rS - WCCoYNhAK3UCgYADaLnCBpZmbGJbimqTEPABXflQR1Vy9WrnthK3NETq1rGEZo9b - k6GH8Yu7aEcsqhnIgA3LeDHWAgAf0Qc9eK0unObS3Ppy7KKh54BvKzF690QhB1Rr - 7yqWKUZxI4M3YETYfj8/JWCtCoBkb9yEBJWL8Xb4dd6Sv4JQ5/dvmQmP8QKBgBX+ - 5+Aeksnik060U36uBV7bW1OcjGKaFALoFsAcILJ53B4Ct5Eyo6jpf6dV8xdA7T9D - Y6JbQOrHkk4AD4uW94Ej0k7s1hjLjg+WVKYzdvejzO2GfyVrFWaiWIo1A8ohHCBR - lI/llAsTb1cLjOnaDIXEILbgqnlGfTh8vvVIKRcJAoGALF6Q1Ca2GIx4kJZ2/Az5 - qx89q95wQoWVHcJCA91g/GKg/bD0ZJMWEhhVH3QcnDOU7afRGKOPGdSSBdPQnspQ - 1OPpPjA3U5Mffy5PJ2bHTpPBeeHOzDO4Jt073zK3N81QovJzS8COoOwuGdcocURH - mFMnEtK7d+EK1C1NTWDyNzU= + """ + MIIEwAIBADANBgkqhkiG9w0BAQEFAASCBKowggSmAgEAAoIBAQDdytxHN5whXTwy + 6HqQDQK5Uqc+RTZssL7pulXv+IFngPeozA7xDTb6A/vWk82gBDWeyJ/FHiT2YFVg + 6NqvflFWm4WYtFFUxquCvGDhZYN9WAsyE54LLz5OXgyn/JEveeSvQwl3ntEI49w8 + Tzgn/UKurUu7Lb6GxdKPbktUkrHajosTS1/A9ae5901QfMdG42gFHzc6mohPS5cf + XlMdlL7RlxDCskxwph7glaXqhdZyxZu1Mb6vtAshEpyTYgbuOMcWkTzdDoi/YeSF + y2AZmh/BJNnIyYnx4KWi+9pYUsNosvZa4jc3Bkz/+SeMzJ+wRa1awgtdrIKfk1NP + vgKVCNZBAgMBAAECggEBAMUMAtJe7J6Tx/TuqF0swfvGHAHt2eGM0cCzpMATh1xe + rylPSgMNG4faXDcSj4AX3U+ZrKCjHHGruo7jsc5yqm8IsxOtOAjajOwU0vnNh5mn + zCKMXUBQk8lqM1JXyOFmKS8wnsug1NRSJIuMUjbtAf5QxlSg2oHAZUa61cBoqAyk + KXbw9uBYnM4n8WGXdax/LLPuonjnz2Sc35CC1LhRAF/K7oyjg7KvScnphIFRaLiU + X4tFH0nLpcao5de0fP5eUEkbUZ3hE6MEZvOsxn5CFkjH2VdtZ9D5dc3ArV3UMe26 + +3swdenriYZ73HNJDiLAdeIVh9IrGVxhH9UowF9psIUCgYEA/Ldlx4vTTlM7URFn + luqK7D8WH9x4JiCLEGxU80nJxxIgF8eqhOFzsQemytTrf4o1xAkyyPIweHzwApCA + lBdwC4Mc44DjoLFVdTET9hEq7E/UK81znc0mD4v8Hz2JI6h3f2sQrcEAPBvjBwtc + TpS9WlSBKSO3NOb3Hlucq7COVKcCgYEA4KyZ+dOyKVLyGjd0g22v4YW7VC016Hql + uQ7SN1vuI3zQMa2rZfEv5z2L7olJKrDFcmqk8W1tfElrMaSsuohm8khhx0lPtHMw + 4Su/tci/3rEUl+DPrQExdjrrDXCqpUunOAlMP9qElsNBGdkrQ6QlMnSVVi2v8Vf1 + f86Mey2UEtcCgYEAqcOlmqPigfZFnZLcjLPoOQW0HhkjmTE5WgH8GybRZmpVpsPZ + V8R/zEeAkzbvMFEvBw7Kz9RqHTaIoKBjz5fjC8i7ClVWFGesKbqbVyx3MiH6PKaa + aUIbtEvsRSw4SPztsWnB3YcOWlK9csj97Efc36Zu0a0NcHtLPFh8aZWEN3cCgYEA + oQFv8oWPlmeXkcwN1iWjtfT1EtS3XhuOaXjCkuNxW8MVG5S+UHawAoGrpsyBP3Og + e2cLPuxRWpDunYvKMH6Rb60JTRwvXzxxWdvVLbtoLHkwLcrwaKWDQZvlWCNWVtBJ + TDH1j4jUHYpdO93SUE3wTiEX58Mj48tJ5kYpjBhUlc8CgYEA7PG3ORGqZtfCiNmj + CxvPtQiFC+ogf+v8cMQtrKVTgpnI2pxzG+cSXYvL4cnyY2JnwqarWorUic8JU2e2 + EhW53PWUg7VpITlLsqOpATIDiviFAN4qOOxgDt5v0C1PyB3aXe2B5VA3IgczssyR + OLy7p/DhOpu2bqnpKyIkAuzZgFc= """), // Version: 3 (0x2) - // Serial Number: 14845986384898254167 (0xce0789f5ac256557) - // Signature Algorithm: sha1WithRSAEncryption - // Issuer: C=US, ST=California, O=Example, OU=Test + // Serial Number: 4099 (0x1003) + // Signature Algorithm: sha256WithRSAEncryption + // Issuer: C = US, ST = California, O = Example, OU = Test // Validity - // Not Before: Jan 26 04:50:29 2022 GMT - // Not After : Feb 25 04:50:29 2022 GMT - // Subject: C=US, ST=California, O=Example, OU=Test, CN=Do-Not-Reply - // Public Key Algorithm: rsaEncryption + // Not Before: Feb 25 20:33:59 2022 GMT + // Not After : Feb 19 20:33:59 2042 GMT + // Subject: C = US, ST = California, O = Example, OU = Test, CN = Do-Not-Reply + // Subject Public Key Info: + // Public Key Algorithm: rsaEncryption + // RSA Public-Key: (2048 bit) CLIENT_EXAMPLE_RSA("RSA", - """ + """ -----BEGIN CERTIFICATE----- - MIIDkjCCAnqgAwIBAgIJAM4HifWsJWVXMA0GCSqGSIb3DQEBBQUAMEMxCzAJBgNV - BAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRAwDgYDVQQKDAdFeGFtcGxlMQ0w - CwYDVQQLDARUZXN0MB4XDTIyMDEyNjA0NTAyOVoXDTIyMDIyNTA0NTAyOVowWjEL - MAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWExEDAOBgNVBAoMB0V4YW1w - bGUxDTALBgNVBAsMBFRlc3QxFTATBgNVBAMMDERvLU5vdC1SZXBseTCCASIwDQYJ - KoZIhvcNAQEBBQADggEPADCCAQoCggEBAODbsCteHcAg3dktUO5fiPTytIahKZMg - U2h6h0+BT803tYcdN6WDHnLNlU/3iFnBMpyTwzWhYIftC9c/TIkXBAGfWl4HHQgc - x08NHPms0E+GF6CDthvHERSvRCBrIyVna0KIZPemBzUfeBeNdiqwsLvg+C5dqWu5 - YcILvL6GzTMvdMwJeEX+c2ZYHibqd8aZydWsT+IPVZnueDX6KTOnYvexLFIoid2a - 62FavnMWiPKnICertDDg+gHlN2XceW3tlYQwO+HMig4DH3u2x0SApOoM3y8k29Ew - Fn6wquSRomcbDiI8SEOeaBFenu6W0g24iaxIZfqEM52kPbQFdzqg+O0CAwEAAaNy - MHAwCQYDVR0TBAIwADAdBgNVHQ4EFgQU0t+I5iAfPq6C/I2CSvTKHGK6+2kwHwYD - VR0jBBgwFoAUwXDYVZS/BnHcUmObUb1O6MKMAlIwIwYDVR0RBBwwGoEYZG8tbm90 - LXJlcGx5QGV4YW1wbGUuY29tMA0GCSqGSIb3DQEBBQUAA4IBAQBqWk35XXpb3L+N - 7kPlNmSlhfamenVOVYxPBq/tSFpl728CV0OrGAy79awEFDvzhpbBg9Mz7HS/a7ax - f+lBbsAt1maWlsVSsaaJrmy3znl9CZiIg+ykZ5ZzLS5FkIbQ6LkzvxYZJ1JYCzXm - P/5+rbQyIvQaDGL23PmE7AB2Q0q+imt4b9HKs+SnI4XERyj8OF/kseRtILtP2ltV - r+3XgcBxwyU17CLwsHrjnQ8/1eGovBKzGAfUXeHBdzOuD3ZemjnqwlzQTf2TAkBP - OuMc8gr2Umc5tMtdiRUFPODO7DG7vB7LKEsJGKWLUtGbR+3S55lIcCF5NFZ//TNZ - 4x2GPOJ+ + MIIDZjCCAk6gAwIBAgICEAMwDQYJKoZIhvcNAQELBQAwQzELMAkGA1UEBhMCVVMx + EzARBgNVBAgTCkNhbGlmb3JuaWExEDAOBgNVBAoTB0V4YW1wbGUxDTALBgNVBAsT + BFRlc3QwHhcNMjIwMjI1MjAzMzU5WhcNNDIwMjE5MjAzMzU5WjBaMQswCQYDVQQG + EwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEQMA4GA1UECgwHRXhhbXBsZTENMAsG + A1UECwwEVGVzdDEVMBMGA1UEAwwMRG8tTm90LVJlcGx5MIIBIjANBgkqhkiG9w0B + AQEFAAOCAQ8AMIIBCgKCAQEA2yJgm3Lthr+97vdEWTb4zaNuLTa/DkCXdmVNIQk9 + kVn2hjZrPc+JghBCaWpohGVTQ+zxplIJXk+QVZ0ePEimE7ahBClz4MlAgMpt1uxy + mYYUAsSZDCaFUI9Cpx1f0BiSWu330196K/AfRIoT+/SOZucnpbepxyrt+Az5SKrH + TJR/OSqeX4XKGPoRI96pKxDOV8pY5/I9h9yKGuxfufbpOdVODngVLcMKgBAkiD+2 + sguEHM+iGLx970+W6yycu1dFY1CAgWLUF3evUxe8avwePgx7lTFXnNueYt96Ny9v + L1o/WzoBe3z1mTl5Qb//3tYbXn8vdiDYm0dT8wImpDbpvwIDAQABo00wSzAJBgNV + HRMEAjAAMB0GA1UdDgQWBBSXqW/B1BVjNgowSwa3MBiHMkzp6zAfBgNVHSMEGDAW + gBQuMz1/AmcLdOnVBgzwc0vLrRu2XTANBgkqhkiG9w0BAQsFAAOCAQEABIMAjT5T + lZDV/1wmdKCyJQJ7WUjA44N5/yBGtEmpAJ0VM7/COnk8lqiYxrk50wK7lt0tiklX + 4aLqbAgnDc27z9AQGHOqB69dZprGQT9PsTByjK6i7KPGs30ygyND41j0rju/GM2e + 3xprZbusODENRyL196QV4ai0WVe1hEvv0wTMIcnXYmZHMP8ArdVRHWaDQF6zW0Mh + QbFqklt5W0ZIl2ZmC8z7z2Z6jv/BYyDo3U96LfdCWsEKxSKiX/PGHqZu4D3A4VSE + 0+fE7cX61kgRdGvZJgFjtYxtfkXd1HlyJ48Dqilzl+rvgvR5XA68zijjN0khPhml + wZhPIOCIaWMZYw== -----END CERTIFICATE-----""", - """ - MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDg27ArXh3AIN3Z - LVDuX4j08rSGoSmTIFNoeodPgU/NN7WHHTelgx5yzZVP94hZwTKck8M1oWCH7QvX - P0yJFwQBn1peBx0IHMdPDRz5rNBPhhegg7YbxxEUr0QgayMlZ2tCiGT3pgc1H3gX - jXYqsLC74PguXalruWHCC7y+hs0zL3TMCXhF/nNmWB4m6nfGmcnVrE/iD1WZ7ng1 - +ikzp2L3sSxSKIndmuthWr5zFojypyAnq7Qw4PoB5Tdl3Hlt7ZWEMDvhzIoOAx97 - tsdEgKTqDN8vJNvRMBZ+sKrkkaJnGw4iPEhDnmgRXp7ultINuImsSGX6hDOdpD20 - BXc6oPjtAgMBAAECggEAKjqX900RoUeK4oKUNHBUtEvwg2g4+pyTjYeVaeULK6tO - uDVQghEB4uWhKQd/3/tcmfNWMfhAvMZT9vS4Vvavle5rdkU3upJNDBeWXX2LEaRJ - Q6f4x3a3Sn8v+DamvxuRFUmwTKItsFhcoW+7xYCxcFdrxKlqbATAy0SRCecfGoFw - 9pAsFIgIqLGQtV9V9fZWKdXIfLkH3venNImHt0n5pYadl4kZu0gNCmOGRO1MqB51 - bdAck3dBg22TE5+sZBIZmCjBAEbrc2RUQu5mAoDs8eeenxBlFYszWZxqM8BkJL5e - SqQkbc18E8Gzdx52xEx6BCLTq0MITKliKX4B2tsQsQKBgQD1DIvt13yg9LlyoiAb - Fc1zzKZQBPRgDUJCGzCPeC6AqbPUjoxvFAHxGNgmJXqAXwsqcs88qlSGAjk6ANAx - fHWUQ3UmkZjGvV0ru3rIPcXvS7isjzm/cbq1YZua6+ohFl4+hojc/iyUrOaCd9uY - V2zwrr+A0JJrlev72niEuAtEmwKBgQDq6CaLP79dHqAOIV43+SyX7KdwNkMMWIR7 - El6E/74V0IWOYWFXLmV4sX6BKi0ZBTFZ3wKwMTDqQBYD2/a7gq43HjzuWu+2dFhA - pCQumMOKNqcNS9NldqoxAiGLxC+JMhGGyf3RO0Ey9gdPnQuje3133Wce8WWaHHv2 - lD5BcmzdFwKBgQCCeca7wiPy07s2ZUqxAT/eq5XWP30a85RW/IEzsusXyMQepjPy - JPYPuInGbeg3F+QrGuxrQco1fFOaJbq0zq8QXYawHY/6KfPFCFMM8Y9FpczT3IME - A3tFfo5Kw9hq+6z8n8eZ26BDHXiy+Tysdchksrb20JdVv4LiG+ZVzGT7hwKBgG+b - Bp0IF4JFh6PPBLWxRBeWT2MH1Mkr0R2r945W91fj72BbMeU63Oj/42u4vx5xEiZx - xxQw+t2AvzTsMAicqOr1CdvxBoz4L+neUnZ1DApBtxKhIPnG7EtGiOuftToIuL0C - gP4EmhB9RbH0mk/83vqxDUptRGl4+QiJHB76H3DXAoGASGT6tfs1/92rGqe0COm3 - aHpelvW7Wwr9AuBumE7/ur/JWAAiM4pm6w7m5H5duYZtG3eWz1s+jvjy8jIPBIkN - RA2DoneC2J/tsRRNFBqZrOWon5Jv4dc9R79qR13B/Oqu8H6FYSB2oDyh67Csud3q - PRrz4o7UKM+HQ/obr1rUYqM= + """ + MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDbImCbcu2Gv73u + 90RZNvjNo24tNr8OQJd2ZU0hCT2RWfaGNms9z4mCEEJpamiEZVND7PGmUgleT5BV + nR48SKYTtqEEKXPgyUCAym3W7HKZhhQCxJkMJoVQj0KnHV/QGJJa7ffTX3or8B9E + ihP79I5m5yelt6nHKu34DPlIqsdMlH85Kp5fhcoY+hEj3qkrEM5Xyljn8j2H3Ioa + 7F+59uk51U4OeBUtwwqAECSIP7ayC4Qcz6IYvH3vT5brLJy7V0VjUICBYtQXd69T + F7xq/B4+DHuVMVec255i33o3L28vWj9bOgF7fPWZOXlBv//e1htefy92INibR1Pz + AiakNum/AgMBAAECggEAW0WxWW4AMyzwDnWdWU+FSBm3TUvNPkF3FNBS1NzFcSI4 + hWRrPJ6R1sOw9blleSe/C77IVA89abPYGWDM9C0KR5G89T/SzSDmJf6qy2dGwF1R + PmnmmWH+CzTwfSzF+KYTZ55QqBDPkTd9vo2Ij1woaAIFyId8RsHBxpyYxESlqGY4 + C6IzEqxFQ0obHXasNR+dP4iOWS4ONhxeUHixcrDHxbmoqmHt0WuJwXhlOjxHgr+i + lUPTe5y+Y2B1gVNYrN4KlDTJqJ6lu4n6MFQ46jhfddzTk3uiEOTVWK6nE8Cf0NM7 + djTzTcR8xAVpoY5XDlk0aBfEd8Np7TLSjV4vU3J04QKBgQD6scazH/H9Yu9ZbR7w + EeN/k7uDDlgahWg8/93syzdFtSNIRGvdalNMhTfM/zXaM/Cl63gvZilWxC+56Uvg + 6QC+rBUwzZrm7ryb6hT6Zyoo4w72bw3jGOJ3e2/bclSLrAcJnL/1Gq87J3CS16wl + NIHrlOlY8orToEdki+6HaagyEQKBgQDfxZz4Uqsa+jDO/rEm959+nz2RkaXYu1Ld + DhYONxmlw69/BbwzOvzr88qKNbd+b+oIK8kpm7Lvpc2/cuqItTFdehmw+tGhMWYo + XizKCeKeCByFTjXI2/PEPUHMy0D8M68Tx/Hq0NbIYqCyzkaamHhXpuJGftxGfd3/ + U0NB4WGOzwKBgQDgnyN7YfcwY1I0XUqoLk8aA2Oy5MpaUQh6B4RwZBENO2T2np/L + TzZ9zKuX2WAGOB26fMY+KhqGLNjaike7qOpK7eM6zC6sFmMWjGHpj0A+TFwewJi/ + z48zIX2zMbjBQQ05NqLkWdmCdi8u02HiIC78x3thgEiVn/n4BE1gNXJIEQKBgEdr + dfcXw36/vZZDWd07CU/LmUX9u3YaC498MHPnCCuM8lVTSkb7m7/fNpS4IlGbfJGR + EApUpF6yh6GEFvD9C71u/AYtd3zAHH/j1t3BG/AeXKP7W1U5RmsqtfacJKiaAlYI + 6eBtOTAJsop/Ja+v3DD1laC0Wq+w+orEU2ISgiWnAoGBAK9/9m3RCYPNYzS/PQ2B + AgE2FQRuY8FXxHegZo2tBBwIojPeVHO1OoThYVNgiQfW9k27dFkRwXVAtt6Jqgax + fvOby8rWRStXH2qHVyvHicceL7iXs6v2bX20Szsy44eMkoFfAImea6ZdErLdVWvI + fxlYpTIVpBt3Nu2BRJn28ili """); final String keyAlgo; @@ -330,10 +370,24 @@ public enum SSLExampleCert { } } + // Set the date for the verifying of certificates. + DateFormat df = new SimpleDateFormat("MM/dd/yyyy"); + Date verifyingDate = df.parse("02/02/2023"); + // Create an SSLContext object. TrustManagerFactory tmf = TrustManagerFactory.getInstance("PKIX"); - tmf.init(ts); + if (ts != null) { + PKIXBuilderParameters pkixParams = + new PKIXBuilderParameters(ts, null); + pkixParams.setDate(verifyingDate); + pkixParams.setRevocationEnabled(false); + ManagerFactoryParameters managerFactoryParameters = + new CertPathTrustManagerParameters(pkixParams); + tmf.init(managerFactoryParameters); + } else { + tmf.init((KeyStore)null); + } SSLContext context = SSLContext.getInstance("TLS"); if (endEntityCerts != null && endEntityCerts.length != 0) { @@ -341,7 +395,16 @@ public enum SSLExampleCert { KeyManagerFactory.getInstance("NewSunX509"); kmf.init(ks, passphrase); - context.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null); + KeyManager[] kms = kmf.getKeyManagers(); + if (kms != null && kms.length != 0) { + KeyManager km = kms[0]; + Field verificationDateField = + km.getClass().getDeclaredField("verificationDate"); + verificationDateField.setAccessible(true); + verificationDateField.set(km, verifyingDate); + } + + context.init(kms, tmf.getTrustManagers(), null); } else { context.init(null, tmf.getTrustManagers(), null); } diff --git a/test/jdk/javax/net/ssl/templates/SSLSocketSSLEngineTemplate.java b/test/jdk/javax/net/ssl/templates/SSLSocketSSLEngineTemplate.java index 54b4e3c68407208023d54c04ec4c163ccb914fc6..cbb42ee1a699bc0a2f2e91e6c26bee587451fcc9 100644 --- a/test/jdk/javax/net/ssl/templates/SSLSocketSSLEngineTemplate.java +++ b/test/jdk/javax/net/ssl/templates/SSLSocketSSLEngineTemplate.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 @@ -349,13 +349,13 @@ public class SSLSocketSSLEngineTemplate { } finally { if (serverException != null) { if (clientException != null) { - serverException.initCause(clientException); + serverException.addSuppressed(clientException); } throw serverException; } if (clientException != null) { if (serverException != null) { - clientException.initCause(serverException); + clientException.addSuppressed(serverException); } throw clientException; } diff --git a/test/jdk/javax/net/ssl/templates/SSLSocketTemplate.java b/test/jdk/javax/net/ssl/templates/SSLSocketTemplate.java index ce2e3ee121be403a8b5c3ad0f9f73ea0794c2212..f200752d2a79985906378cdd82b37becfff9d97d 100644 --- a/test/jdk/javax/net/ssl/templates/SSLSocketTemplate.java +++ b/test/jdk/javax/net/ssl/templates/SSLSocketTemplate.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 @@ -544,7 +544,7 @@ public class SSLSocketTemplate { */ if ((local != null) && (remote != null)) { // If both failed, return the curthread's exception. - local.initCause(remote); + local.addSuppressed(remote); exception = local; } else if (local != null) { exception = local; diff --git a/test/jdk/javax/sound/midi/Gervill/ModelIdentifier/NewModelIdentifierStringStringInt.java b/test/jdk/javax/sound/midi/Gervill/ModelIdentifier/NewModelIdentifierStringStringInt.java index 348012f54bfccdcdd5515f2d92ca3ef4a64506cf..fdd6e542440970e3fe75f021ded039de75cf52c3 100644 --- a/test/jdk/javax/sound/midi/Gervill/ModelIdentifier/NewModelIdentifierStringStringInt.java +++ b/test/jdk/javax/sound/midi/Gervill/ModelIdentifier/NewModelIdentifierStringStringInt.java @@ -37,7 +37,7 @@ import com.sun.media.sound.*; public class NewModelIdentifierStringStringInt { public static void main(String[] args) throws Exception { - ModelIdentifier id = new ModelIdentifier("test","a",1);; + ModelIdentifier id = new ModelIdentifier("test","a",1); if(!id.getObject().equals("test")) throw new RuntimeException("id.getObject() doesn't return \"test\"!"); if(!id.getVariable().equals("a")) diff --git a/test/jdk/javax/sound/midi/Gervill/SoftChannel/NoteOff.java b/test/jdk/javax/sound/midi/Gervill/SoftChannel/NoteOff.java index 0330628c8b61fe479bb17abaff61ac79bc0e52cb..eaff35c2c3cef03355497a48fe52f098e796a8a8 100644 --- a/test/jdk/javax/sound/midi/Gervill/SoftChannel/NoteOff.java +++ b/test/jdk/javax/sound/midi/Gervill/SoftChannel/NoteOff.java @@ -56,7 +56,7 @@ public class NoteOff { assertEquals(v[0].active, true); channel.noteOff(60); soft.read(1); - v = soft.synth.getVoiceStatus();; + v = soft.synth.getVoiceStatus(); assertEquals(v[0].active, false); soft.close(); diff --git a/test/jdk/javax/sound/midi/Gervill/SoftChannel/NoteOff2.java b/test/jdk/javax/sound/midi/Gervill/SoftChannel/NoteOff2.java index 71172a049daaecdf8728cb1983b5e820fa9bc95e..8143ee846a5537f6c09d5fd22cc82be5ade3c2fa 100644 --- a/test/jdk/javax/sound/midi/Gervill/SoftChannel/NoteOff2.java +++ b/test/jdk/javax/sound/midi/Gervill/SoftChannel/NoteOff2.java @@ -56,7 +56,7 @@ public class NoteOff2 { assertEquals(v[0].active, true); channel.noteOff(60); soft.read(1); - v = soft.synth.getVoiceStatus();; + v = soft.synth.getVoiceStatus(); assertEquals(v[0].active, false); soft.close(); diff --git a/test/jdk/javax/sql/testng/test/rowset/BaseRowSetTests.java b/test/jdk/javax/sql/testng/test/rowset/BaseRowSetTests.java index 95883556a057ead3ec21c4201219494b9c93960e..c1d2d9a2ed018754ad16160d817226ab012b1f29 100644 --- a/test/jdk/javax/sql/testng/test/rowset/BaseRowSetTests.java +++ b/test/jdk/javax/sql/testng/test/rowset/BaseRowSetTests.java @@ -355,7 +355,7 @@ public class BaseRowSetTests extends CommonRowSetTests { Blob aBlob = new SerialBlob(new StubBlob()); Clob aClob = new SerialClob(new StubClob()); Reader rdr = new StringReader(query); - InputStream is = new StringBufferInputStream(query);; + InputStream is = new StringBufferInputStream(query); brs = new StubBaseRowSet(); brs.setBytes(1, bytes); brs.setAsciiStream(2, is, query.length()); diff --git a/test/jdk/javax/sql/testng/test/rowset/serial/SQLInputImplTests.java b/test/jdk/javax/sql/testng/test/rowset/serial/SQLInputImplTests.java index a6756a13a4ad40f623d93c1164171ac1e2a7ef52..95cc508828a08f918c04f6ac858b9d64e6a0d22c 100644 --- a/test/jdk/javax/sql/testng/test/rowset/serial/SQLInputImplTests.java +++ b/test/jdk/javax/sql/testng/test/rowset/serial/SQLInputImplTests.java @@ -183,7 +183,7 @@ public class SQLInputImplTests extends BaseTest { */ @Test(enabled = true) public void test10() throws Exception { - URL u = new URL("http://www.oracle.com/");; + URL u = new URL("http://www.oracle.com/"); Object[] values = {u}; SQLInputImpl sqli = new SQLInputImpl(values, map); URL u2 = sqli.readURL(); diff --git a/test/jdk/javax/sql/testng/test/rowset/serial/SerialArrayTests.java b/test/jdk/javax/sql/testng/test/rowset/serial/SerialArrayTests.java index 077ce43da85f38f2601eb1d58c5b299b4578bbd1..345315b7f05faead6506bb53b62e84bfe3b154cc 100644 --- a/test/jdk/javax/sql/testng/test/rowset/serial/SerialArrayTests.java +++ b/test/jdk/javax/sql/testng/test/rowset/serial/SerialArrayTests.java @@ -230,7 +230,7 @@ public class SerialArrayTests extends BaseTest { @Test public void test18() throws Exception { SerialArray sa = new SerialArray(a); - SerialArray sa1 = serializeDeserializeObject(sa);; + SerialArray sa1 = serializeDeserializeObject(sa); assertTrue(sa.equals(sa1)); } } diff --git a/test/jdk/javax/sql/testng/test/rowset/serial/SerialExceptionTests.java b/test/jdk/javax/sql/testng/test/rowset/serial/SerialExceptionTests.java index ff963ae7ba84db25d1c9148c13e397c308192c2f..8ef215584a94bdbac29cc2da00099e1e2d8a1c59 100644 --- a/test/jdk/javax/sql/testng/test/rowset/serial/SerialExceptionTests.java +++ b/test/jdk/javax/sql/testng/test/rowset/serial/SerialExceptionTests.java @@ -108,6 +108,6 @@ public class SerialExceptionTests extends BaseTest { assertTrue(ex1.getMessage().equals(reason) && ex1.getSQLState() == null && ex1.getCause() == null - && ex1.getErrorCode() == 0);; + && ex1.getErrorCode() == 0); } } diff --git a/test/jdk/javax/sql/testng/test/rowset/serial/SerialStructTests.java b/test/jdk/javax/sql/testng/test/rowset/serial/SerialStructTests.java index 84a0ff2aaaf73904b15aeb0014a993e62ea5f98b..79ac2421c9aca44037d254dd187cb3ad40806a47 100644 --- a/test/jdk/javax/sql/testng/test/rowset/serial/SerialStructTests.java +++ b/test/jdk/javax/sql/testng/test/rowset/serial/SerialStructTests.java @@ -134,7 +134,7 @@ public class SerialStructTests extends BaseTest { @Test public void test08() throws Exception { SerialStruct ss = new SerialStruct(struct, map); - SerialStruct ss1 = serializeDeserializeObject(ss);; + SerialStruct ss1 = serializeDeserializeObject(ss); assertTrue(ss.equals(ss1)); } } diff --git a/test/jdk/javax/swing/JButton/4659800/SpaceKeyActivatesButton.java b/test/jdk/javax/swing/JButton/4659800/SpaceKeyActivatesButton.java new file mode 100644 index 0000000000000000000000000000000000000000..a54c97993a097f6a7968789e8f42a4078e0bb791 --- /dev/null +++ b/test/jdk/javax/swing/JButton/4659800/SpaceKeyActivatesButton.java @@ -0,0 +1,152 @@ +/* + * 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.Robot; +import java.awt.event.FocusAdapter; +import java.awt.event.FocusEvent; +import java.awt.event.KeyEvent; +import java.util.Arrays; +import java.util.List; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicBoolean; +import javax.swing.JButton; +import javax.swing.JFrame; +import javax.swing.JPanel; +import javax.swing.SwingUtilities; +import javax.swing.UIManager; +import javax.swing.UnsupportedLookAndFeelException; + + +import static java.util.stream.Collectors.toList; + +/* + * @test + * @key headful + * @bug 8281738 + * @summary Check whether pressing key generates + * ActionEvent on focused Button or not. + * @run main SpaceKeyActivatesButton + */ +public class SpaceKeyActivatesButton { + + private static volatile boolean buttonPressed; + private static JFrame frame; + private static JButton focusedButton; + private static CountDownLatch buttonGainedFocusLatch; + + public static void main(String[] s) throws Exception { + runTest(); + } + + public static void runTest() throws Exception { + Robot robot = new Robot(); + robot.setAutoDelay(100); + robot.setAutoWaitForIdle(true); + + List lafs = Arrays.stream(UIManager.getInstalledLookAndFeels()) + .map(laf -> laf.getClassName()) + .collect(toList()); + for (String laf : lafs) { + buttonGainedFocusLatch = new CountDownLatch(1); + try { + buttonPressed = false; + System.out.println("Testing laf : " + laf); + AtomicBoolean lafSetSuccess = new AtomicBoolean(false); + SwingUtilities.invokeAndWait(() -> { + lafSetSuccess.set(setLookAndFeel(laf)); + // Call createUI() only if setting laf succeeded + if (lafSetSuccess.get()) { + createUI(); + } + }); + // If setting laf failed, then just get next laf and continue + if (!lafSetSuccess.get()) { + continue; + } + robot.waitForIdle(); + + // Wait until the button2 gains focus. + if (!buttonGainedFocusLatch.await(3, TimeUnit.SECONDS)) { + throw new RuntimeException("Test Failed, waited too long, " + + "but the button can't gain focus for laf : " + laf); + } + + robot.keyPress(KeyEvent.VK_SPACE); + robot.keyRelease(KeyEvent.VK_SPACE); + + if (buttonPressed) { + System.out.println("Test Passed for laf : " + laf); + } else { + throw new RuntimeException("Test Failed, button not pressed for laf : " + laf); + } + + } finally { + SwingUtilities.invokeAndWait(SpaceKeyActivatesButton::disposeFrame); + } + } + + } + + private static boolean setLookAndFeel(String lafName) { + try { + UIManager.setLookAndFeel(lafName); + } catch (UnsupportedLookAndFeelException ignored) { + System.out.println("Ignoring Unsupported laf : " + lafName); + return false; + } catch (ClassNotFoundException | InstantiationException + | IllegalAccessException e) { + throw new RuntimeException(e); + } + return true; + } + + private static void createUI() { + frame = new JFrame(); + JPanel panel = new JPanel(); + panel.add(new JButton("Button1")); + focusedButton = new JButton("Button2"); + focusedButton.addActionListener(e -> buttonPressed = true); + focusedButton.addFocusListener(new FocusAdapter() { + @Override + public void focusGained(FocusEvent e) { + buttonGainedFocusLatch.countDown(); + } + }); + panel.add(focusedButton); + + frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); + frame.add(panel); + frame.pack(); + frame.setLocationRelativeTo(null); + frame.setVisible(true); + focusedButton.requestFocusInWindow(); + } + + private static void disposeFrame() { + if (frame != null) { + frame.dispose(); + frame = null; + } + } +} diff --git a/test/jdk/javax/swing/JButton/HtmlButtonImageTest/HtmlButtonImageTest.java b/test/jdk/javax/swing/JButton/HtmlButtonImageTest/HtmlButtonImageTest.java new file mode 100644 index 0000000000000000000000000000000000000000..b7fed2cff030d6b527b0174281e20b194cc7442b --- /dev/null +++ b/test/jdk/javax/swing/JButton/HtmlButtonImageTest/HtmlButtonImageTest.java @@ -0,0 +1,115 @@ +/* + * 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 8015854 + * @requires (os.family == "mac") + * @summary Tests HTML image as JButton text for unwanted padding on macOS Aqua LAF + * @run main HtmlButtonImageTest + */ + +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Graphics2D; +import java.awt.image.BufferedImage; +import java.io.File; +import java.io.IOException; +import java.nio.file.Path; + +import javax.imageio.ImageIO; +import javax.swing.JButton; +import javax.swing.SwingUtilities; +import javax.swing.UIManager; + +import static java.awt.image.BufferedImage.TYPE_INT_ARGB; + +public final class HtmlButtonImageTest { + private static JButton button; + private static Path testDir; + private static BufferedImage image; + + private static final int BUTTON_HEIGHT = 37; + private static final int BUTTON_WIDTH = 37; + private static final int SQUARE_HEIGHT = 19; + private static final int SQUARE_WIDTH = 19; + private static final int centerX = BUTTON_WIDTH / 2; + private static final int centerY = BUTTON_HEIGHT / 2; + private static final int minX = centerX - (SQUARE_WIDTH / 2); + private static final int minY = centerY - (SQUARE_HEIGHT / 2); + private static final int maxX = centerX + (SQUARE_WIDTH / 2); + private static final int maxY = centerY + (SQUARE_HEIGHT / 2); + + public static void main(String[] args) throws Exception { + UIManager.setLookAndFeel("com.apple.laf.AquaLookAndFeel"); + testDir = Path.of(System.getProperty("test.classes", ".")); + generateRedSquare(); + + SwingUtilities.invokeAndWait(HtmlButtonImageTest::createButton); + SwingUtilities.invokeAndWait(HtmlButtonImageTest::paintButton); + + testImageCentering(image.getRGB(centerX, centerY), + image.getRGB(minX, minY), + image.getRGB(minX, maxY), + image.getRGB(maxX, minY), + image.getRGB(maxX, maxY)); + } + + private static void generateRedSquare() throws IOException { + BufferedImage bImg = new BufferedImage(SQUARE_WIDTH, SQUARE_HEIGHT, + TYPE_INT_ARGB); + Graphics2D cg = bImg.createGraphics(); + cg.setColor(Color.RED); + cg.fillRect(0, 0, SQUARE_WIDTH, SQUARE_HEIGHT); + ImageIO.write(bImg, "png", new File(testDir + "/red_square.png")); + } + + private static void createButton() { + button = new JButton(); + button.setSize(new Dimension(BUTTON_WIDTH, BUTTON_HEIGHT)); + button.setText(""); + } + + private static void paintButton() { + image = new BufferedImage(BUTTON_HEIGHT, BUTTON_WIDTH, TYPE_INT_ARGB); + Graphics2D graphics2D = image.createGraphics(); + button.paint(graphics2D); + graphics2D.dispose(); + } + + private static boolean checkRedColor(int rgb) { + return (rgb == Color.RED.getRGB()); + } + + private static void testImageCentering(int... colors) throws IOException { + for (int c : colors) { + if (!checkRedColor(c)) { + ImageIO.write(image, "png", + new File(testDir + "/fail_image.png")); + throw new RuntimeException("HTML image not centered in button"); + } + } + System.out.println("Passed"); + } +} diff --git a/test/jdk/javax/swing/JEditorPane/4330998/JEditorPaneSetTextNullTest.java b/test/jdk/javax/swing/JEditorPane/4330998/JEditorPaneSetTextNullTest.java new file mode 100644 index 0000000000000000000000000000000000000000..5b543894ef6c613e4361c843088a2f9e700867b4 --- /dev/null +++ b/test/jdk/javax/swing/JEditorPane/4330998/JEditorPaneSetTextNullTest.java @@ -0,0 +1,45 @@ + /* + * Copyright (c) 2013, 2022, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + + import javax.swing.JEditorPane; + import javax.swing.SwingUtilities; + + /* + * @test + * @bug 4330998 + * @summary Verifies that JEditorPane.setText(null) doesn't throw NullPointerException. + * @run main JEditorPaneSetTextNullTest + */ + public class JEditorPaneSetTextNullTest { + + public static void main(String[] args) throws Exception { + try { + SwingUtilities.invokeAndWait(() -> new JEditorPane().setText(null)); + System.out.println("Test passed"); + } catch (Exception e) { + throw new RuntimeException("Test failed, caught Exception " + e + + " when calling JEditorPane.setText(null)"); + } + } + + } diff --git a/test/jdk/javax/swing/JEditorPane/4666101/JEditorPaneNavigationTest.java b/test/jdk/javax/swing/JEditorPane/4666101/JEditorPaneNavigationTest.java new file mode 100644 index 0000000000000000000000000000000000000000..c88e284556e69f802cc3fde23235f5486c040d58 --- /dev/null +++ b/test/jdk/javax/swing/JEditorPane/4666101/JEditorPaneNavigationTest.java @@ -0,0 +1,197 @@ +/* + * 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 + * 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.Point; +import java.awt.Rectangle; +import java.awt.Robot; +import java.awt.Toolkit; +import java.awt.event.InputEvent; +import java.awt.event.KeyEvent; +import java.io.File; +import java.io.IOException; +import java.util.Arrays; +import java.util.List; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicReference; +import java.util.stream.Collectors; +import javax.imageio.ImageIO; +import javax.swing.JEditorPane; +import javax.swing.JFrame; +import javax.swing.JPanel; +import javax.swing.SwingUtilities; +import javax.swing.UIManager; +import javax.swing.UIManager.LookAndFeelInfo; +import javax.swing.UnsupportedLookAndFeelException; + +import static javax.swing.UIManager.getInstalledLookAndFeels; + +/* + * @test + * @key headful + * @bug 4666101 + * @summary Verifies that in a JEditorPane, the down arrow is honoured after you + add text on a line preceding a blank line. + * @run main JEditorPaneNavigationTest + */ +public class JEditorPaneNavigationTest { + + private static volatile int caretPos; + private static JEditorPane jep; + private static JFrame frame; + private static Robot robot; + + public static void main(String[] args) throws Exception { + robot = new Robot(); + robot.setAutoWaitForIdle(true); + robot.setAutoDelay(100); + + List lafs = Arrays.stream(getInstalledLookAndFeels()) + .map(LookAndFeelInfo::getClassName) + .collect(Collectors.toList()); + for (final String laf : lafs) { + try { + AtomicBoolean lafSetSuccess = new AtomicBoolean(false); + SwingUtilities.invokeAndWait(() -> { + lafSetSuccess.set(setLookAndFeel(laf)); + if (lafSetSuccess.get()) { + createUI(); + } + }); + if (!lafSetSuccess.get()) { + continue; + } + robot.waitForIdle(); + + AtomicReference pt = new AtomicReference<>(); + SwingUtilities.invokeAndWait(() -> pt.set(jep.getLocationOnScreen())); + caretPos = 0; + final Point jEditorLoc = pt.get(); + + // Click on JEditorPane + robot.mouseMove(jEditorLoc.x + 50, jEditorLoc.y + 50); + robot.mousePress(InputEvent.BUTTON1_DOWN_MASK); + robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); + + keyType(KeyEvent.VK_ENTER); + keyType(KeyEvent.VK_ENTER); + + typeSomeText(); + + keyType(KeyEvent.VK_UP); + keyType(KeyEvent.VK_UP); + + typeSomeText(); + + keyType(KeyEvent.VK_DOWN); + + System.out.println(" test1 caret pos = " + caretPos); + + // Check whether the caret position is at the expected value 5 + if (caretPos != 5) { + captureScreen(); + throw new RuntimeException("Test Failed in " + laf + + " expected initial caret position is 5, but actual is " + caretPos); + } + + keyType(KeyEvent.VK_DOWN); + + System.out.println(" test2 caret pos = " + caretPos); + + // Check whether the caret position is at the expected value 10 + if (caretPos != 10) { + captureScreen(); + throw new RuntimeException("Test Failed in " + laf + + " expected final caret position is 10, but actual is " + caretPos); + } + + System.out.println("Test Passed in " + laf); + + } finally { + SwingUtilities.invokeAndWait(JEditorPaneNavigationTest::disposeFrame); + } + } + } + + private static void captureScreen() { + Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); + try { + ImageIO.write( + robot.createScreenCapture(new Rectangle(0, 0, screenSize.width, screenSize.height)), + "png", + new File("JEditorPaneNavigationTest.png") + ); + } catch (IOException ignore) { + } + } + + private static void typeSomeText() { + keyType(KeyEvent.VK_T); + keyType(KeyEvent.VK_E); + keyType(KeyEvent.VK_X); + keyType(KeyEvent.VK_T); + } + + private static void keyType(int keyCode) { + robot.keyPress(keyCode); + robot.keyRelease(keyCode); + } + + + private static void createUI() { + frame = new JFrame(); + jep = new JEditorPane(); + jep.setPreferredSize(new Dimension(100, 100)); + jep.addCaretListener(e -> caretPos = jep.getCaretPosition()); + jep.setEditable(true); + JPanel panel = new JPanel(); + panel.add(jep); + frame.add(panel); + frame.setLocationRelativeTo(null); + frame.setAlwaysOnTop(true); + frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); + frame.pack(); + frame.setVisible(true); + } + + private static boolean setLookAndFeel(String lafName) { + try { + UIManager.setLookAndFeel(lafName); + } catch (UnsupportedLookAndFeelException ignored) { + System.out.println("Ignoring Unsupported laf : " + lafName); + return false; + } catch (ClassNotFoundException | InstantiationException + | IllegalAccessException e) { + throw new RuntimeException(e); + } + return true; + } + + private static void disposeFrame() { + if (frame != null) { + frame.dispose(); + frame = null; + } + } + +} diff --git a/test/jdk/javax/swing/JList/4618767/JListSelectedElementTest.java b/test/jdk/javax/swing/JList/4618767/JListSelectedElementTest.java new file mode 100644 index 0000000000000000000000000000000000000000..5eca0f3232ef655e1a5915768035bc89ad38d1a5 --- /dev/null +++ b/test/jdk/javax/swing/JList/4618767/JListSelectedElementTest.java @@ -0,0 +1,222 @@ +/* + * 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 + * 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.Robot; +import java.awt.event.FocusAdapter; +import java.awt.event.FocusEvent; +import java.awt.event.KeyEvent; +import java.util.Arrays; +import java.util.List; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicReference; +import java.util.stream.Collectors; +import javax.swing.JFrame; +import javax.swing.JList; +import javax.swing.JMenu; +import javax.swing.JMenuBar; +import javax.swing.JMenuItem; +import javax.swing.SwingUtilities; +import javax.swing.UIManager; +import javax.swing.UIManager.LookAndFeelInfo; +import javax.swing.UnsupportedLookAndFeelException; +import javax.swing.event.MenuEvent; +import javax.swing.event.MenuListener; + + +import static javax.swing.UIManager.getInstalledLookAndFeels; + +/* + * @test + * @key headful + * @bug 4618767 + * @summary This test confirms that typing a letter while a JList has focus now makes the selection + * not jump to the item whose text starts with that letter if that typed letter is accompanied + * by modifier keys such as ALT or CTRL(eg: ALT+F). + * @run main JListSelectedElementTest + */ +public class JListSelectedElementTest { + + private static final int FILE_MENU = KeyEvent.VK_F; + private static JFrame frame; + private static JList list; + private static Robot robot; + private static CountDownLatch listGainedFocusLatch; + private static CountDownLatch menuSelectedEventLatch; + + public static void main(String[] args) throws Exception { + runTest(); + } + + public static void runTest() throws Exception { + robot = new Robot(); + robot.setAutoWaitForIdle(true); + robot.setAutoDelay(200); + + final boolean isMac = System.getProperty("os.name") + .toLowerCase() + .contains("os x"); + + List lafs = Arrays.stream(getInstalledLookAndFeels()) + .map(LookAndFeelInfo::getClassName) + .collect(Collectors.toList()); + for (final String laf : lafs) { + listGainedFocusLatch = new CountDownLatch(1); + menuSelectedEventLatch = new CountDownLatch(1); + try { + AtomicBoolean lafSetSuccess = new AtomicBoolean(false); + SwingUtilities.invokeAndWait(() -> { + lafSetSuccess.set(setLookAndFeel(laf)); + if (lafSetSuccess.get()) { + createUI(); + } + }); + if (!lafSetSuccess.get()) { + continue; + } + robot.waitForIdle(); + + // Wait until the list gains focus. + if (!listGainedFocusLatch.await(3, TimeUnit.SECONDS)) { + throw new RuntimeException("Waited too long, but can't gain focus for list"); + } + + // Select element named as 'bill' + hitKeys(KeyEvent.VK_B); + + // Assertion check to verify that the selected node is 'bill' + AtomicReference elementSel = new AtomicReference<>(); + SwingUtilities.invokeAndWait(() -> elementSel.set(list.getSelectedValue())); + final String elementSelBefore = elementSel.get(); + if (!"bill".equals(elementSelBefore)) { + throw new RuntimeException("Test failed for " + laf + + " as the list element selected: " + elementSel + + " is not the expected one 'bill'" + ); + } + + // Now operate Menu using Mnemonics, different key combinations for different OSes. + // For most OSes it's ALT+F; on macOS it's ALT+CNTRL+F except for Nimbus LaF. + if (isMac && !laf.contains("Nimbus")) { + hitKeys(KeyEvent.VK_ALT, KeyEvent.VK_CONTROL, FILE_MENU); + } else { + hitKeys(KeyEvent.VK_ALT, FILE_MENU); + } + + // Wait until the menu got selected. + if (!menuSelectedEventLatch.await(3, TimeUnit.SECONDS)) { + throw new RuntimeException("Waited too long, but can't select menu using mnemonics for " + laf); + } + + hitKeys(KeyEvent.VK_ENTER); + + AtomicReference elementSelAfter = new AtomicReference<>(); + SwingUtilities.invokeAndWait(() -> elementSelAfter.set(list.getSelectedValue())); + + // As per the fix of BugID 4618767, the list element selection should not change + if (!elementSelBefore.equals(elementSelAfter.get())) { + throw new RuntimeException("Test failed for " + laf + + " as list.getSelectedValue() before = " + elementSel + + " not equal to list.getSelectedValue() after pressing Enter = " + elementSelAfter + ); + } + System.out.println("Test passed for laf: " + laf); + + } finally { + SwingUtilities.invokeAndWait(JListSelectedElementTest::disposeFrame); + } + } + } + + private static void hitKeys(int... keys) { + for (int key : keys) { + robot.keyPress(key); + } + + for (int i = keys.length - 1; i >= 0; i--) { + robot.keyRelease(keys[i]); + } + } + + private static void createUI() { + frame = new JFrame(); + list = new JList<>(new String[]{"anaheim", "bill", "chicago", "dingo", "ernie", "freak"}); + list.addFocusListener(new FocusAdapter() { + @Override + public void focusGained(FocusEvent e) { + listGainedFocusLatch.countDown(); + } + }); + JMenu menu = new JMenu("File"); + menu.setMnemonic(FILE_MENU); + JMenuItem menuItem = new JMenuItem("Dummy"); + menu.add(menuItem); + menu.addMenuListener(new MenuListener() { + @Override + public void menuSelected(MenuEvent e) { + menuSelectedEventLatch.countDown(); + } + + @Override + public void menuDeselected(MenuEvent e) { + } + + @Override + public void menuCanceled(MenuEvent e) { + } + }); + + JMenuBar menuBar = new JMenuBar(); + menuBar.add(menu); + + frame.setJMenuBar(menuBar); + frame.setContentPane(list); + frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); + frame.pack(); + frame.setAlwaysOnTop(true); + frame.setLocationRelativeTo(null); + frame.setVisible(true); + } + + private static boolean setLookAndFeel(String lafName) { + try { + UIManager.setLookAndFeel(lafName); + } catch (UnsupportedLookAndFeelException ignored) { + System.out.println("Ignoring Unsupported L&F: " + lafName); + return false; + } catch (ClassNotFoundException | InstantiationException + | IllegalAccessException e) { + throw new RuntimeException(e); + } + return true; + } + + private static void disposeFrame() { + if (frame != null) { + frame.dispose(); + frame = null; + } + } + +} diff --git a/test/jdk/javax/swing/JMenuBar/MenuBarRTLBug.java b/test/jdk/javax/swing/JMenuBar/MenuBarRTLBug.java new file mode 100644 index 0000000000000000000000000000000000000000..454ae03b126d118c8544b4442818bc4dd2c876b3 --- /dev/null +++ b/test/jdk/javax/swing/JMenuBar/MenuBarRTLBug.java @@ -0,0 +1,178 @@ +/* + * 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.awt.ComponentOrientation; +import java.awt.Point; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.InputEvent; +import java.awt.event.KeyEvent; +import java.awt.Robot; + +import javax.swing.JFrame; +import javax.swing.JMenu; +import javax.swing.JMenuBar; +import javax.swing.JMenuItem; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; +import javax.swing.event.MenuEvent; +import javax.swing.event.MenuListener; +import javax.swing.SwingUtilities; +import javax.swing.UIManager; +import javax.swing.UnsupportedLookAndFeelException; + +/* + * @test + * @key headful + * @bug 8277369 + * @summary Verifies arrow traversal in RTL orientation in JMenuBar + */ +public class MenuBarRTLBug { + + static JFrame frame; + static JMenuBar menuBar; + static JMenu firstMenu; + static JMenuItem a; + static JMenuItem b; + static JMenu secondMenu; + static JMenuItem c; + static JMenuItem d; + static JMenu thirdMenu; + static JMenuItem e; + static JMenuItem f; + static JMenu forthMenu; + static JMenu fifthMenu; + + static Point p; + static int width; + static int height; + + static volatile boolean passed = false; + + private static void setLookAndFeel(UIManager.LookAndFeelInfo laf) { + try { + UIManager.setLookAndFeel(laf.getClassName()); + } catch (UnsupportedLookAndFeelException ignored) { + System.out.println("Unsupported L&F: " + laf.getClassName()); + } catch (ClassNotFoundException | InstantiationException + | IllegalAccessException e) { + throw new RuntimeException(e); + } + } + + public static void main(String[] args) throws Exception { + + for (UIManager.LookAndFeelInfo laf : UIManager.getInstalledLookAndFeels()) { + System.out.println("Testing L&F: " + laf.getClassName()); + passed = false; + SwingUtilities.invokeAndWait(() -> setLookAndFeel(laf)); + try { + SwingUtilities.invokeAndWait(() -> { + frame = new JFrame(); + frame.setLayout(new BorderLayout()); + + firstMenu = new JMenu("first"); + a = new JMenuItem("a"); + b = new JMenuItem("b"); + firstMenu.add(a); + firstMenu.add(b); + + secondMenu = new JMenu("second"); + c = new JMenuItem("c"); + d = new JMenuItem("d"); + secondMenu.add(c); + secondMenu.add(d); + secondMenu.addMenuListener(new MenuListener() { + @Override + public void menuSelected(MenuEvent e) { + passed = true; + } + @Override + public void menuDeselected(MenuEvent e) { + } + + @Override + public void menuCanceled(MenuEvent e) { + } + }); + + thirdMenu = new JMenu("third"); + e = new JMenuItem("e"); + f = new JMenuItem("f"); + thirdMenu.add(e); + thirdMenu.add(f); + + forthMenu = new JMenu("fourth"); + e = new JMenuItem("e"); + f = new JMenuItem("f"); + forthMenu.add(e); + forthMenu.add(f); + + fifthMenu = new JMenu("fifth"); + e = new JMenuItem("e"); + f = new JMenuItem("f"); + fifthMenu.add(e); + fifthMenu.add(f); + + menuBar = new JMenuBar(); + menuBar.setComponentOrientation(ComponentOrientation.RIGHT_TO_LEFT); + menuBar.add(firstMenu); + menuBar.add(secondMenu); + menuBar.add(thirdMenu); + menuBar.add(forthMenu); + menuBar.add(fifthMenu); + frame.setJMenuBar(menuBar); + + frame.setLocationRelativeTo(null); + frame.pack(); + frame.setVisible(true); + }); + Robot robot = new Robot(); + robot.setAutoDelay(100); + robot.waitForIdle(); + robot.delay(1000); + SwingUtilities.invokeAndWait(() -> { + p = thirdMenu.getLocationOnScreen(); + width = thirdMenu.getWidth(); + height = thirdMenu.getHeight(); + }); + robot.mouseMove(p.x + width / 2, p.y + height / 2); + robot.mousePress(InputEvent.BUTTON1_DOWN_MASK); + robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); + robot.delay(1000); + robot.keyPress(KeyEvent.VK_RIGHT); + robot.keyRelease(KeyEvent.VK_RIGHT); + robot.delay(1000); + if (!passed) { + throw new RuntimeException("Arrow traversal order not correct in RTL orientation"); + } + } finally { + SwingUtilities.invokeAndWait(() -> { + if (frame != null) { + frame.dispose(); + } + }); + } + } + } +} diff --git a/test/jdk/javax/swing/JPasswordField/TestSelectedTextBackgroundColor.java b/test/jdk/javax/swing/JPasswordField/TestSelectedTextBackgroundColor.java index fc5bbd3e183635bb571c787477928e0eb39d5d69..b4b527eaf0a4d15a997faa31d527151f3078ff73 100644 --- a/test/jdk/javax/swing/JPasswordField/TestSelectedTextBackgroundColor.java +++ b/test/jdk/javax/swing/JPasswordField/TestSelectedTextBackgroundColor.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 @@ -103,7 +103,7 @@ public class TestSelectedTextBackgroundColor { panel.add(passwordField, BorderLayout.CENTER); frame = new JFrame("TestSelectedTextBackgroundColor"); frame.add(panel); - frame.setSize(200, 200); + frame.setSize(400, 400); frame.setAlwaysOnTop(true); frame.setLocationRelativeTo(null); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); diff --git a/test/jdk/javax/swing/JProgressBar/TestJProgressBarHighlightColor.java b/test/jdk/javax/swing/JProgressBar/TestJProgressBarHighlightColor.java index c3c37d06123dc34e3baafffa14da50ba15107b61..731e30841807563770bbe33a051362666f0da7bc 100644 --- a/test/jdk/javax/swing/JProgressBar/TestJProgressBarHighlightColor.java +++ b/test/jdk/javax/swing/JProgressBar/TestJProgressBarHighlightColor.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 @@ -103,7 +103,7 @@ public class TestJProgressBarHighlightColor { panel.add(progressBar, BorderLayout.CENTER); frame = new JFrame("TestSelectedTextBackgroundColor"); frame.add(panel); - frame.setSize(200, 200); + frame.setSize(400, 400); frame.setAlwaysOnTop(true); frame.setLocationRelativeTo(null); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); diff --git a/test/jdk/javax/swing/JScrollPane/TestMouseWheelScroll.java b/test/jdk/javax/swing/JScrollPane/TestMouseWheelScroll.java new file mode 100644 index 0000000000000000000000000000000000000000..180a697a3f385b3ae380320b18d15d6e04eb3083 --- /dev/null +++ b/test/jdk/javax/swing/JScrollPane/TestMouseWheelScroll.java @@ -0,0 +1,127 @@ +/* + * 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.Point; +import java.awt.Robot; +import java.awt.event.InputEvent; +import javax.swing.DefaultListModel; +import javax.swing.ListModel; +import javax.swing.JScrollPane; +import javax.swing.JFrame; +import javax.swing.JList; +import javax.swing.SwingUtilities; +import javax.swing.UIManager; +import javax.swing.UnsupportedLookAndFeelException; + +/* + * @test + * @key headful + * @requires (os.family != "mac") + * @bug 6911375 + * @summary Verifies mouseWheel effect on JList without scrollBar + */ +public class TestMouseWheelScroll { + + static JFrame frame; + static JScrollPane scrollPane; + static volatile Point p; + static volatile int width; + static volatile int height; + static volatile Point viewPosition; + static volatile Point newPosition; + + private static void setLookAndFeel(UIManager.LookAndFeelInfo laf) { + try { + UIManager.setLookAndFeel(laf.getClassName()); + } catch (UnsupportedLookAndFeelException ignored) { + System.out.println("Unsupported L&F: " + laf.getClassName()); + } catch (ClassNotFoundException | InstantiationException + | IllegalAccessException e) { + throw new RuntimeException(e); + } + } + + public static void main(String[] args) throws Exception { + + for (UIManager.LookAndFeelInfo laf : UIManager.getInstalledLookAndFeels()) { + System.out.println("Testing L&F: " + laf.getClassName()); + SwingUtilities.invokeAndWait(() -> setLookAndFeel(laf)); + Robot robot = new Robot(); + robot.setAutoDelay(100); + + try { + SwingUtilities.invokeAndWait(() -> { + frame = new JFrame(); + JList list = new JList(createListModel()); + // disable list bindings + list.getInputMap().getParent().clear(); + scrollPane = new JScrollPane(list); + + scrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_NEVER); + frame.add(scrollPane); + frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); + frame.setSize(200,200); + frame.setLocationRelativeTo(null); + frame.setVisible(true); + }); + robot.waitForIdle(); + robot.delay(1000); + SwingUtilities.invokeAndWait(() -> { + p = frame.getLocationOnScreen(); + width = frame.getWidth(); + height = frame.getHeight(); + }); + robot.mouseMove(p.x + width / 2, p.y + height / 2); + robot.mousePress(InputEvent.BUTTON1_DOWN_MASK); + robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); + robot.waitForIdle(); + SwingUtilities.invokeAndWait(() -> { + viewPosition = scrollPane.getViewport().getViewPosition(); + }); + robot.delay(1000); + robot.mouseWheel(1); + robot.delay(500); + SwingUtilities.invokeAndWait(() -> { + newPosition = scrollPane.getViewport().getViewPosition(); + }); + robot.delay(1000); + if (newPosition.equals(viewPosition)) { + throw new RuntimeException("Mouse wheel not handled"); + } + } finally { + SwingUtilities.invokeAndWait(() -> { + if (frame != null) { + frame.dispose(); + } + }); + } + } + } + + private static ListModel createListModel() { + DefaultListModel model = new DefaultListModel(); + for (int i = 0; i < 100; i++) { + model.addElement("element " + i); + } + return model; + } +} diff --git a/test/jdk/javax/swing/JSlider/TestJSliderRendering.java b/test/jdk/javax/swing/JSlider/TestJSliderRendering.java index ebf12021ced8652e3bc672c1612f7a6af294b609..5ece0a8852ea1ed8cd67de11acb53e86439205cd 100644 --- a/test/jdk/javax/swing/JSlider/TestJSliderRendering.java +++ b/test/jdk/javax/swing/JSlider/TestJSliderRendering.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 @@ -101,7 +101,7 @@ public class TestJSliderRendering { panel.add(slider); frame = new JFrame("TestJSliderRendering"); frame.add(panel); - frame.setSize(200, 200); + frame.setSize(400, 400); frame.setAlwaysOnTop(true); frame.setLocationRelativeTo(null); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); diff --git a/test/jdk/javax/swing/JSpinner/4515999/JSpinnerMouseAndKeyPressTest.java b/test/jdk/javax/swing/JSpinner/4515999/JSpinnerMouseAndKeyPressTest.java index 6e5fb3ad97fc6e55f4d265178ac392c50449f5e4..49a237a1e27f2bcb0b433648c3f2cfc8a1cde0ba 100644 --- a/test/jdk/javax/swing/JSpinner/4515999/JSpinnerMouseAndKeyPressTest.java +++ b/test/jdk/javax/swing/JSpinner/4515999/JSpinnerMouseAndKeyPressTest.java @@ -83,6 +83,7 @@ public class JSpinnerMouseAndKeyPressTest { panel.add(spinner); frame.add(panel); frame.setUndecorated(true); + frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); frame.pack(); frame.setAlwaysOnTop(true); frame.setLocationRelativeTo(null); @@ -103,6 +104,7 @@ public class JSpinnerMouseAndKeyPressTest { setLookAndFeel(laf); createUI(); }); + robot.waitForIdle(); SwingUtilities.invokeAndWait(() -> { Point loc = spinner.getLocationOnScreen(); diff --git a/test/jdk/javax/swing/JSpinner/TestSelectedTextBackgroundColor.java b/test/jdk/javax/swing/JSpinner/TestSelectedTextBackgroundColor.java index 300c8fed80ea0291bb8b1f8f52155b2c997410bb..16f19feb60791182b2b19d6436c2435ae6f0f76f 100644 --- a/test/jdk/javax/swing/JSpinner/TestSelectedTextBackgroundColor.java +++ b/test/jdk/javax/swing/JSpinner/TestSelectedTextBackgroundColor.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 @@ -119,7 +119,7 @@ public class TestSelectedTextBackgroundColor { panel.add(listModelSpinner, BorderLayout.CENTER); frame = new JFrame("TestSelectedTextBackgroundColor"); frame.add(panel); - frame.setSize(200, 200); + frame.setSize(400, 400); frame.setAlwaysOnTop(true); frame.setLocationRelativeTo(null); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); diff --git a/test/jdk/javax/swing/JSplitPane/4820080/JSplitPaneDragColorTest.java b/test/jdk/javax/swing/JSplitPane/4820080/JSplitPaneDragColorTest.java new file mode 100644 index 0000000000000000000000000000000000000000..7e107f1265c75437af370e97b4bc27b47fc06778 --- /dev/null +++ b/test/jdk/javax/swing/JSplitPane/4820080/JSplitPaneDragColorTest.java @@ -0,0 +1,205 @@ +/* + * 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 + * 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.awt.Color; +import java.awt.Dimension; +import java.awt.Point; +import java.awt.Rectangle; +import java.awt.Robot; +import java.awt.Toolkit; +import java.awt.event.InputEvent; +import java.io.File; +import java.io.IOException; +import java.util.Arrays; +import java.util.List; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicReference; +import java.util.stream.Collectors; +import javax.imageio.ImageIO; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JSplitPane; +import javax.swing.SwingUtilities; +import javax.swing.UIManager; +import javax.swing.UIManager.LookAndFeelInfo; +import javax.swing.UnsupportedLookAndFeelException; + +import static javax.swing.UIManager.getInstalledLookAndFeels; + +/* + * @test + * @key headful + * @bug 4820080 + * @summary This test confirms that the Drag color of JSplitPane divider should + * be the user specified one(Red here). + * @run main JSplitPaneDragColorTest + */ +public class JSplitPaneDragColorTest { + + // Tolerance is set inorder to negate small differences in pixel color values, + // especially in Mac machines. + private final static int COLOR_TOLERANCE = 9; + private static final Color EXPECTED_DRAG_COLOR = Color.RED; + private static JFrame frame; + private static JSplitPane pane; + private static Robot robot; + + public static void main(String[] args) throws Exception { + + robot = new Robot(); + robot.setAutoWaitForIdle(true); + robot.setAutoDelay(200); + // Skipping NimbusLookAndFeel & GTKLookAndFeel, + // as both are not supported for this feature - JDK-8075914, JDK-8075608 + List lafs = Arrays.stream(getInstalledLookAndFeels()) + .filter(laf -> !(laf.getName().contains("GTK") + || laf.getName().contains("Nimbus"))) + .map(LookAndFeelInfo::getClassName) + .collect(Collectors.toList()); + for (final String laf : lafs) { + try { + AtomicBoolean lafSetSuccess = new AtomicBoolean(false); + SwingUtilities.invokeAndWait(() -> { + lafSetSuccess.set(setLookAndFeel(laf)); + if (lafSetSuccess.get()) { + createUI(); + } + }); + if (!lafSetSuccess.get()) { + continue; + } + robot.waitForIdle(); + + Rectangle dividerRect = getDividerRect(); + + // Mouse click and right drag split pane divider + robot.mouseMove(dividerRect.x + 5, dividerRect.y + 36); + robot.mousePress(InputEvent.BUTTON1_DOWN_MASK); + robot.mouseMove(dividerRect.x + 15, dividerRect.y + 36); + robot.mouseMove(dividerRect.x + 5, dividerRect.y + 36); + + // Get the color of one of the pixels of the splitpane divider + // after the drag has started. Ideally it should be the + // SplitPaneDivider.draggingColor set by user, otherwise the test fails + final Color actualDragColor = robot.getPixelColor(dividerRect.x + 2, + dividerRect.y + 2); + if (checkDragColor(actualDragColor)) { + System.out.println("Test passed in " + laf); + } else { + System.out.print("Expected pixel color = "); + System.out.printf("%X", EXPECTED_DRAG_COLOR.getRGB()); + System.out.print(", but actual color = "); + System.out.printf("%X", actualDragColor.getRGB()); + System.out.println(); + captureScreen(); + throw new RuntimeException("Test failed, drag color is wrong in " + + laf); + } + } finally { + robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); + SwingUtilities.invokeAndWait(JSplitPaneDragColorTest::disposeFrame); + } + } + } + + private static boolean checkDragColor(Color actualDragColor) { + int actualRed = actualDragColor.getRed(); + int actualGreen = actualDragColor.getGreen(); + int actualBlue = actualDragColor.getBlue(); + int expectedRed = EXPECTED_DRAG_COLOR.getRed(); + int expectedGreen = EXPECTED_DRAG_COLOR.getGreen(); + int expectedBlue = EXPECTED_DRAG_COLOR.getBlue(); + + final double tolerance = Math.sqrt( + (actualRed - expectedRed) * (actualRed - expectedRed) + + (actualGreen - expectedGreen) * (actualGreen - expectedGreen) + + (actualBlue - expectedBlue) * (actualBlue - expectedBlue)); + return (tolerance <= COLOR_TOLERANCE); + } + + private static Rectangle getDividerRect() { + final AtomicReference rect = new AtomicReference<>(); + SwingUtilities.invokeLater(() -> { + javax.swing.plaf.basic.BasicSplitPaneUI ui = + (javax.swing.plaf.basic.BasicSplitPaneUI) pane.getUI(); + + javax.swing.plaf.basic.BasicSplitPaneDivider divider = ui.getDivider(); + Point dividerLoc = divider.getLocationOnScreen(); + rect.set(new Rectangle(dividerLoc.x, dividerLoc.y, divider.getWidth(), + divider.getHeight())); + }); + robot.waitForIdle(); + return rect.get(); + } + + private static void captureScreen() { + Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); + try { + ImageIO.write( + robot.createScreenCapture(new Rectangle(0, 0, + screenSize.width, + screenSize.height)), + "png", + new File("screen1.png") + ); + } catch (IOException ignore) { + } + } + + private static void createUI() { + frame = new JFrame(); + UIManager.put("SplitPaneDivider.draggingColor", EXPECTED_DRAG_COLOR); + JLabel l1 = new JLabel("LEFT LABEL", JLabel.CENTER); + JLabel l2 = new JLabel("RIGHT LABEL", JLabel.CENTER); + pane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, l1, l2); + frame.setSize(400, 400); + pane.setDividerSize(15); + pane.setDividerLocation(frame.getSize().width / 2); + frame.getContentPane().add(pane, BorderLayout.CENTER); + frame.setLocationRelativeTo(null); + frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); + frame.setVisible(true); + } + + private static boolean setLookAndFeel(String lafName) { + try { + UIManager.setLookAndFeel(lafName); + } catch (UnsupportedLookAndFeelException ignored) { + System.out.println("Ignoring Unsupported L&F: " + lafName); + return false; + } catch (ClassNotFoundException | InstantiationException + | IllegalAccessException e) { + throw new RuntimeException(e); + } + return true; + } + + private static void disposeFrame() { + if (frame != null) { + frame.dispose(); + frame = null; + } + } + +} diff --git a/test/jdk/javax/swing/JTable/8236907/LastVisibleRow.java b/test/jdk/javax/swing/JTable/8236907/LastVisibleRow.java new file mode 100644 index 0000000000000000000000000000000000000000..6ca33c9635631628d1a160d99dd91f276702c72b --- /dev/null +++ b/test/jdk/javax/swing/JTable/8236907/LastVisibleRow.java @@ -0,0 +1,221 @@ +/* + * 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 headful + * @bug 8236907 + * @summary Verifies if JTable last row is visible. + * @run main LastVisibleRow + */ + +import java.awt.BorderLayout; +import java.awt.Container; +import java.awt.Dimension; +import java.awt.event.InputEvent; +import java.awt.image.BufferedImage; +import java.awt.Point; +import java.awt.Rectangle; +import java.awt.Robot; +import java.lang.reflect.InvocationTargetException; + +import javax.print.attribute.HashPrintRequestAttributeSet; +import javax.print.attribute.PrintRequestAttributeSet; + +import javax.swing.BorderFactory; +import javax.swing.JFrame; +import javax.swing.JPanel; +import javax.swing.JTable; +import javax.swing.SwingUtilities; +import javax.swing.WindowConstants; + +public class LastVisibleRow { + static JFrame frame; + static JTable table; + static Robot testRobot; + + public static void main(String[] args) throws Exception { + Point clkPoint; + try { + testRobot = new Robot(); + + SwingUtilities.invokeAndWait(new Runnable() { + + public void run() { + createAndShowGUI(); + } + }); + testRobot.delay(1000); + testRobot.waitForIdle(); + BufferedImage bufferedImageBefore = testRobot.createScreenCapture(getCaptureRect()); + testRobot.delay(1000); + testRobot.waitForIdle(); + clkPoint = getMousePosition(); + mouseEvents(clkPoint); + testRobot.waitForIdle(); + clearSelect(); + testRobot.waitForIdle(); + BufferedImage bufferedImageAfter = testRobot.createScreenCapture(getCaptureRect()); + testRobot.delay(1000); + + if (!compare(bufferedImageBefore, bufferedImageAfter)) { + throw new RuntimeException("Test Case Failed!!"); + } + } finally { + if (frame != null) SwingUtilities.invokeAndWait(() -> frame.dispose()); + } + } + + /* + * + * Get clickable screen point for particular row and column of a table + * param row Row Number + * param column Column Number + * return Point + */ + private static Point getCellClickPoint(final int row, final int column) { + Point result; + + Rectangle rect = table.getCellRect(row, column, false); + Point point = new Point(rect.x + rect.width / 2, + rect.y + rect.height / 2); + SwingUtilities.convertPointToScreen(point, table); + result = point; + + return result; + } + + private static void createAndShowGUI() { + final PrintRequestAttributeSet printReqAttr = new HashPrintRequestAttributeSet(); + printReqAttr.add(javax.print.attribute.standard.OrientationRequested.LANDSCAPE); + frame = new JFrame(); + frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); + Container contentPane = frame.getContentPane(); + JPanel centerPane = new JPanel(new BorderLayout()); + centerPane.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10)); + JPanel tablePaneContainer = new JPanel(new BorderLayout()); + JPanel tablePane = new JPanel(new BorderLayout()); + table = new JTable(new Object[][]{{"row_1_col_1", "row_1_col_2", "row_1_col_3"}, {"row_2_col_1", "row_2_col_2", "row_2_col_3"}, {"row_3_col_1", "row_3_col_2", "row_3_col_3"}, {"row_4_col_1", "row_4_col_2", "row_4_col_3"}}, new String[]{"Col1", "Col2", "Col3"}); + table.setPreferredSize(new Dimension(0, (table.getRowHeight() * 3))); + + tablePane.add(table.getTableHeader(), BorderLayout.NORTH); + tablePane.add(table, BorderLayout.CENTER); + tablePaneContainer.add(tablePane, BorderLayout.CENTER); + centerPane.add(tablePaneContainer, BorderLayout.NORTH); + contentPane.add(centerPane, BorderLayout.CENTER); + frame.setSize(400, 120); + frame.setVisible(true); + frame.setLocationRelativeTo(null); + + } + + /* + * + * mouseEvents for last row click + */ + + private static void mouseEvents(Point clkPnt) { + testRobot.mouseMove(clkPnt.x, clkPnt.y); + testRobot.delay(50); + testRobot.mousePress(InputEvent.BUTTON1_DOWN_MASK); + testRobot.delay(50); + testRobot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); + testRobot.delay(50); + } + /* + * + * getMousePosition Actions for last row click + * returns Point + * throws Exception + */ + + private static Point getMousePosition() throws Exception { + final Point[] clickPoint = new Point[1]; + SwingUtilities.invokeAndWait(new Runnable() { + @Override + public void run() { + clickPoint[0] = getCellClickPoint(2, 0); + } + }); + return clickPoint[0]; + } + + /* + * + * Clears the selected table row + * throws Exception + */ + + private static void clearSelect() throws Exception { + SwingUtilities.invokeAndWait(new Runnable() { + @Override + public void run() { + table.getSelectionModel().clearSelection(); + table.setFocusable(false); + } + }); + } + + /* + * getCaptureRect Method - To Compute the Rectangle for + * Screen Capturing the Last Row for comparison + * return Rectangle + */ + + private static Rectangle getCaptureRect() throws InterruptedException, InvocationTargetException { + final Rectangle[] captureRect = new Rectangle[1]; + SwingUtilities.invokeAndWait(new Runnable() { + @Override + public void run() { + Rectangle cellRect = table.getCellRect(2, 0, true); + Point point = new Point(cellRect.x, cellRect.y); + SwingUtilities.convertPointToScreen(point, table); + + captureRect[0] = new Rectangle(point.x, point.y, table.getColumnCount() * cellRect.width, cellRect.height); + } + }); + return captureRect[0]; + } + + /* + * Compare method - to compare two images. + * param bufferedImage1 Buffered Image Before click + * param bufferedImage2 Buffered Image After click + * return Boolean + */ + + static Boolean compare(BufferedImage bufferedImage1, BufferedImage bufferedImage2) { + if (bufferedImage1.getWidth() == bufferedImage2.getWidth() + && bufferedImage1.getHeight() == bufferedImage2.getHeight()) { + for (int x = 0; x < bufferedImage1.getWidth(); x++) { + for (int y = 0; y < bufferedImage1.getHeight(); y++) { + if (bufferedImage1.getRGB(x, y) != bufferedImage2.getRGB(x, y)) { + return false; + } + } + } + } else { + return false; + } + return true; + } +} diff --git a/test/jdk/javax/swing/JTextArea/4514331/TabShiftsFocusToNextComponent.java b/test/jdk/javax/swing/JTextArea/4514331/TabShiftsFocusToNextComponent.java new file mode 100644 index 0000000000000000000000000000000000000000..88e123aed54fbe10819e62a102c9c80a5e7aa53e --- /dev/null +++ b/test/jdk/javax/swing/JTextArea/4514331/TabShiftsFocusToNextComponent.java @@ -0,0 +1,176 @@ +/* + * 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 + * 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.Point; +import java.awt.Robot; +import java.awt.event.FocusAdapter; +import java.awt.event.FocusEvent; +import java.awt.event.InputEvent; +import java.awt.event.KeyEvent; +import java.util.Arrays; +import java.util.List; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicReference; +import java.util.stream.Collectors; +import javax.swing.JButton; +import javax.swing.JFrame; +import javax.swing.JPanel; +import javax.swing.JTextArea; +import javax.swing.SwingUtilities; +import javax.swing.UIManager; +import javax.swing.UnsupportedLookAndFeelException; + + +import static javax.swing.UIManager.getInstalledLookAndFeels; + +/* + * @test + * @key headful + * @bug 4514331 + * @summary Check whether pressing key always shift focus to next component, + * even though the current focus is in JTextArea and some text is already selected. + * @run main TabShiftsFocusToNextComponent + */ +public class TabShiftsFocusToNextComponent { + + private static JFrame frame; + private static JTextArea textArea; + private static Robot robot; + private static CountDownLatch textAreaGainedFocusLatch; + private static CountDownLatch buttonGainedFocusLatch; + + public static void main(String[] s) throws Exception { + runTest(); + } + + public static void runTest() throws Exception { + robot = new Robot(); + robot.setAutoWaitForIdle(true); + robot.setAutoDelay(200); + List lafs = Arrays.stream(getInstalledLookAndFeels()) + .map(UIManager.LookAndFeelInfo::getClassName) + .collect(Collectors.toList()); + for (final String laf : lafs) { + textAreaGainedFocusLatch = new CountDownLatch(1); + buttonGainedFocusLatch = new CountDownLatch(1); + try { + AtomicBoolean lafSetSuccess = new AtomicBoolean(false); + SwingUtilities.invokeAndWait(() -> { + lafSetSuccess.set(setLookAndFeel(laf)); + if (lafSetSuccess.get()) { + createUI(); + } + }); + if (!lafSetSuccess.get()) { + continue; + } + robot.waitForIdle(); + + SwingUtilities.invokeAndWait(() -> textArea.requestFocusInWindow()); + + // Waits until the textArea gains focus. + if (!textAreaGainedFocusLatch.await(3, TimeUnit.SECONDS)) { + throw new RuntimeException("Test Failed, waited for long, " + + "but the JTextArea can't gain focus for L&F: " + laf); + } + + AtomicReference textAreaLoc = new AtomicReference(); + SwingUtilities.invokeAndWait(() -> { + textAreaLoc.set(textArea.getLocationOnScreen()); + }); + + final int x = textAreaLoc.get().x; + final int y = textAreaLoc.get().y; + robot.mouseMove(x + 5, y + 5); + robot.mousePress(InputEvent.BUTTON1_DOWN_MASK); + robot.mouseMove(x + 20, y + 5); + robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); + robot.keyPress(KeyEvent.VK_TAB); + robot.keyRelease(KeyEvent.VK_TAB); + + // Waits until the button gains focus. + if (!buttonGainedFocusLatch.await(3, TimeUnit.SECONDS)) { + throw new RuntimeException("Test Failed, waited for long, " + + "but the Button can't gain focus when 'Tab' key pressed for L&F: " + laf); + } else { + System.out.println(" Test passed for " + laf); + } + } finally { + SwingUtilities.invokeAndWait(TabShiftsFocusToNextComponent::disposeFrame); + } + } + } + + + private static void createUI() { + frame = new JFrame(); + JPanel panel = new JPanel(); + textArea = new JTextArea("I am a JTextArea"); + textArea.addFocusListener(new FocusAdapter() { + @Override + public void focusGained(FocusEvent e) { + textAreaGainedFocusLatch.countDown(); + } + }); + textArea.setEditable(false); + panel.add(textArea); + JButton button = new JButton("Button"); + panel.add(button); + button.addFocusListener(new FocusAdapter() { + @Override + public void focusGained(FocusEvent e) { + buttonGainedFocusLatch.countDown(); + } + }); + + frame.add(panel); + frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); + frame.setUndecorated(true); + frame.pack(); + frame.setAlwaysOnTop(true); + frame.setLocationRelativeTo(null); + frame.setVisible(true); + } + + private static boolean setLookAndFeel(String lafName) { + try { + UIManager.setLookAndFeel(lafName); + } catch (UnsupportedLookAndFeelException ignored) { + System.out.println("Ignoring Unsupported L&F: " + lafName); + return false; + } catch (ClassNotFoundException | InstantiationException + | IllegalAccessException e) { + throw new RuntimeException(e); + } + return true; + } + + private static void disposeFrame() { + if (frame != null) { + frame.dispose(); + frame = null; + } + } +} diff --git a/test/jdk/javax/swing/JTextField/4532513/DefaultCaretRequestsFocusTest.java b/test/jdk/javax/swing/JTextField/4532513/DefaultCaretRequestsFocusTest.java new file mode 100644 index 0000000000000000000000000000000000000000..b2fec6d9f94a33bbbed894e69ebe04ec2aa5dd1d --- /dev/null +++ b/test/jdk/javax/swing/JTextField/4532513/DefaultCaretRequestsFocusTest.java @@ -0,0 +1,193 @@ +/* + * 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 + * 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.GridLayout; +import java.awt.Point; +import java.awt.Robot; +import java.awt.event.InputEvent; +import java.awt.event.KeyEvent; +import java.util.Arrays; +import java.util.List; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicReference; +import java.util.stream.Collectors; +import javax.swing.InputVerifier; +import javax.swing.JComponent; +import javax.swing.JFrame; +import javax.swing.JPanel; +import javax.swing.JTextField; +import javax.swing.SwingUtilities; +import javax.swing.UIManager; +import javax.swing.UIManager.LookAndFeelInfo; +import javax.swing.UnsupportedLookAndFeelException; + +import static javax.swing.UIManager.getInstalledLookAndFeels; + +/* + * @test + * @key headful + * @bug 4532513 + * @summary Verifies that DefaultCaret doesn't requests focus in mouseClick and mousePressed + * causing the associated input verifier to fire twice. + * @run main DefaultCaretRequestsFocusTest + */ +public class DefaultCaretRequestsFocusTest { + + private static JTextField jTextField1; + private static JTextField jTextField2; + private static JTextField jTextField3; + private static JFrame frame; + private static Robot robot; + private static volatile int shouldYieldFocusCount; + + public static void main(String[] args) throws Exception { + runTest(); + } + + public static void runTest() throws Exception { + robot = new Robot(); + robot.setAutoWaitForIdle(true); + robot.setAutoDelay(200); + + List lafs = Arrays.stream(getInstalledLookAndFeels()) + .map(LookAndFeelInfo::getClassName) + .collect(Collectors.toList()); + for (final String laf : lafs) { + try { + AtomicBoolean lafSetSuccess = new AtomicBoolean(false); + SwingUtilities.invokeAndWait(() -> { + lafSetSuccess.set(setLookAndFeel(laf)); + if (lafSetSuccess.get()) { + createUI(); + } + }); + if (!lafSetSuccess.get()) { + continue; + } + robot.waitForIdle(); + + AtomicReference jTextField1LocRef = new AtomicReference<>(); + AtomicReference jTextField2LocRef = new AtomicReference<>(); + SwingUtilities.invokeAndWait(() -> { + jTextField1LocRef.set(jTextField1.getLocationOnScreen()); + jTextField2LocRef.set(jTextField2.getLocationOnScreen()); + }); + final Point jTextField1Loc = jTextField1LocRef.get(); + final Point jTextField2Loc = jTextField2LocRef.get(); + + shouldYieldFocusCount = 0; + + // Click on TextField2 + robot.mouseMove(jTextField2Loc.x + 5, jTextField2Loc.y + 5); + robot.mousePress(InputEvent.BUTTON1_DOWN_MASK); + robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); + + typeSomeText(); + + // Click on TextField1 + robot.mouseMove(jTextField1Loc.x + 5, jTextField1Loc.y + 5); + robot.mousePress(InputEvent.BUTTON1_DOWN_MASK); + robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); + + typeSomeText(); + + if (shouldYieldFocusCount == 1) { + System.out.println("Test passed for " + laf); + } else { + throw new RuntimeException("Test failed for " + laf + + " as InputVerifier.shouldYieldFocus() was called " + shouldYieldFocusCount + + " times on jTextField2, but it is expected to be called only once."); + } + + } finally { + SwingUtilities.invokeAndWait(DefaultCaretRequestsFocusTest::disposeFrame); + } + } + } + + private static void typeSomeText() { + robot.keyPress(KeyEvent.VK_T); + robot.keyRelease(KeyEvent.VK_T); + robot.keyPress(KeyEvent.VK_E); + robot.keyRelease(KeyEvent.VK_E); + robot.keyPress(KeyEvent.VK_X); + robot.keyRelease(KeyEvent.VK_X); + robot.keyPress(KeyEvent.VK_T); + robot.keyRelease(KeyEvent.VK_T); + } + + private static void createUI() { + frame = new JFrame(); + jTextField1 = new JTextField(6); + jTextField2 = new JTextField(6); + jTextField3 = new JTextField(6); + JPanel panel = new JPanel(); + panel.setLayout(new GridLayout(3, 1)); + panel.add(jTextField1); + panel.add(jTextField2); + panel.add(jTextField3); + + InputVerifier iv = new InputVerifier() { + public boolean verify(JComponent input) { + System.out.println("InputVerifier.verify() called"); + return false; + } + + public boolean shouldYieldFocus(JComponent input) { + ++shouldYieldFocusCount; + System.out.println("InputVerifier.shouldYieldFocus() called " + shouldYieldFocusCount); + return false; + } + }; + + jTextField2.setInputVerifier(iv); + + frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); + frame.add(panel); + frame.pack(); + frame.setAlwaysOnTop(true); + frame.setLocationRelativeTo(null); + frame.setVisible(true); + } + + private static boolean setLookAndFeel(String lafName) { + try { + UIManager.setLookAndFeel(lafName); + } catch (UnsupportedLookAndFeelException ignored) { + System.out.println("Ignoring Unsupported laf : " + lafName); + return false; + } catch (ClassNotFoundException | InstantiationException + | IllegalAccessException e) { + throw new RuntimeException(e); + } + return true; + } + + private static void disposeFrame() { + if (frame != null) { + frame.dispose(); + frame = null; + } + } + +} diff --git a/test/jdk/javax/swing/JTextField/SwingUnicodeTest.java b/test/jdk/javax/swing/JTextField/SwingUnicodeTest.java new file mode 100644 index 0000000000000000000000000000000000000000..94053602de5ffcf18e8f07115c39f8116f02db38 --- /dev/null +++ b/test/jdk/javax/swing/JTextField/SwingUnicodeTest.java @@ -0,0 +1,38 @@ +/* + * 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.swing.SwingUtilities; +import javax.swing.JTextField; + +/* + * @test + * @bug 8037965 + * @summary Verifies NPE in TextLayout.getBaselineFromGraphic() for invalid + * Unicode characters + */ +public class SwingUnicodeTest { + public static void main(String[] args) throws Exception { + SwingUtilities.invokeAndWait(() -> + new JTextField(new StringBuilder().appendCodePoint(0xFFFF). + appendCodePoint(0x10000).toString())); + } +} diff --git a/test/jdk/javax/swing/JTextPane/TestJTextPaneBackgroundColor.java b/test/jdk/javax/swing/JTextPane/TestJTextPaneBackgroundColor.java index 99bc3a43f8ab9b119cf64c0e79b5c4ef5e5ed59e..67ceb534da07391bdc18229b06268a5c0238d522 100644 --- a/test/jdk/javax/swing/JTextPane/TestJTextPaneBackgroundColor.java +++ b/test/jdk/javax/swing/JTextPane/TestJTextPaneBackgroundColor.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 @@ -96,7 +96,7 @@ public class TestJTextPaneBackgroundColor { panel.add(textPane, BorderLayout.CENTER); frame = new JFrame("TestJTextPaneBackgroundColor"); frame.add(panel); - frame.setSize(200, 200); + frame.setSize(400, 400); frame.setAlwaysOnTop(true); frame.setLocationRelativeTo(null); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); diff --git a/test/jdk/javax/swing/JToolTip/TestTooltipBackgroundColor.java b/test/jdk/javax/swing/JToolTip/TestTooltipBackgroundColor.java index 678bbbc4c7723f5b7637a73513a51232cc12f096..eb52a27d108926e49be3f7ebbd271b1e1a4deda8 100644 --- a/test/jdk/javax/swing/JToolTip/TestTooltipBackgroundColor.java +++ b/test/jdk/javax/swing/JToolTip/TestTooltipBackgroundColor.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 @@ -134,7 +134,7 @@ public class TestTooltipBackgroundColor { panel.add(label, BorderLayout.CENTER); frame = new JFrame("TestTooltipBackgroundColor"); frame.add(panel); - frame.setSize(200, 200); + frame.setSize(400, 400); frame.setAlwaysOnTop(true); frame.setLocationRelativeTo(null); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); diff --git a/test/jdk/javax/swing/JTree/4518432/JTreeNodeCopyPasteTest.java b/test/jdk/javax/swing/JTree/4518432/JTreeNodeCopyPasteTest.java new file mode 100644 index 0000000000000000000000000000000000000000..7ca69edfa228bc60862bc573ebb204357d1d371e --- /dev/null +++ b/test/jdk/javax/swing/JTree/4518432/JTreeNodeCopyPasteTest.java @@ -0,0 +1,217 @@ +/* + * 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 + * 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.Point; +import java.awt.Rectangle; +import java.awt.Robot; +import java.awt.event.InputEvent; +import java.awt.event.KeyEvent; +import java.util.Arrays; +import java.util.List; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicReference; +import java.util.stream.Collectors; +import javax.swing.JFrame; +import javax.swing.JTree; +import javax.swing.SwingUtilities; +import javax.swing.UIManager; +import javax.swing.UIManager.LookAndFeelInfo; +import javax.swing.UnsupportedLookAndFeelException; + +import static javax.swing.UIManager.getInstalledLookAndFeels; + +/* + * @test + * @key headful + * @bug 4518432 + * @summary Verifies that Copying from JTree node and then changing the data in the component that was copied from, + * is not causing the pastes to use the new edited data instead of the original copied data. + * @run main JTreeNodeCopyPasteTest + */ +public class JTreeNodeCopyPasteTest { + + private static JFrame frame; + private static JTree tree; + private static Robot robot; + private static boolean isMac; + + public static void main(String[] args) throws Exception { + runTest(); + } + + private static void runTest() throws Exception { + isMac = System.getProperty("os.name").toLowerCase().contains("os x"); + robot = new Robot(); + robot.setAutoDelay(100); + robot.setAutoWaitForIdle(true); + + // Filter out Motif laf, as it doesn't support copy-paste in JTree. + List lafs = Arrays.stream(getInstalledLookAndFeels()) + .filter(laf -> !laf.getName().contains("Motif")) + .map(LookAndFeelInfo::getClassName) + .collect(Collectors.toList()); + for (final String laf : lafs) { + try { + AtomicBoolean lafSetSuccess = new AtomicBoolean(false); + SwingUtilities.invokeAndWait(() -> { + lafSetSuccess.set(setLookAndFeel(laf)); + if (lafSetSuccess.get()) { + createUI(); + } + }); + if (!lafSetSuccess.get()) { + continue; + } + + robot.waitForIdle(); + + // Select the node named as 'colors' + Point pt = getNodeLocation(1); + robot.mouseMove(pt.x, pt.y); + robot.mousePress(InputEvent.BUTTON1_DOWN_MASK); + robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); + + String expectedNodeName = getCurrentNodeName(); + + // Copy the contents of that node + copyOrPaste(KeyEvent.VK_C, laf); + + // Edit the Contents of that cell + mouseTripleClick(); + + typeSomeText(); + + robot.keyPress(KeyEvent.VK_ENTER); + robot.keyRelease(KeyEvent.VK_ENTER); + + // Select next node + pt = getNodeLocation(2); + robot.mouseMove(pt.x, pt.y); + + // Edit the Contents of that cell + mouseTripleClick(); + + // paste the content copied earlier + copyOrPaste(KeyEvent.VK_V, laf); + + robot.keyPress(KeyEvent.VK_ENTER); + robot.keyRelease(KeyEvent.VK_ENTER); + + // Now get the node contents of second node + String actualNodeName = getCurrentNodeName(); + + if (expectedNodeName.equals(actualNodeName)) { + System.out.println("Test Passed in " + laf); + } else { + throw new RuntimeException("Test Failed in " + laf + ", Expected : " + expectedNodeName + + ", but actual : " + actualNodeName); + } + } finally { + SwingUtilities.invokeAndWait(JTreeNodeCopyPasteTest::disposeFrame); + } + } + } + + private static String getCurrentNodeName() throws Exception { + AtomicReference nodeName = new AtomicReference<>(); + SwingUtilities.invokeAndWait(() -> { + nodeName.set(tree.getLastSelectedPathComponent().toString().trim()); + }); + return nodeName.get(); + } + + private static Point getNodeLocation(int rowCount) throws Exception { + AtomicReference treeNodeLoc = new AtomicReference<>(); + SwingUtilities.invokeAndWait(() -> { + final Point locationOnScreen = tree.getLocationOnScreen(); + Rectangle rt = tree.getPathBounds(tree.getPathForRow(rowCount)); + locationOnScreen.translate((int) (rt.getX() + rt.getWidth() / 2), (int) (rt.getY() + rt.getHeight() / 2)); + treeNodeLoc.set(locationOnScreen); + }); + return treeNodeLoc.get(); + } + + private static void copyOrPaste(int keyCode, String laf) { + // For AquaLookAndFeel in Mac, the key combination for copy/paste is META + (C or V) + // For other OSes and other lafs, the key combination is CONTROL + (C or V) + robot.keyPress(isMac && laf.contains("Aqua") ? KeyEvent.VK_META : KeyEvent.VK_CONTROL); + robot.keyPress(keyCode); + robot.keyRelease(keyCode); + robot.keyRelease(isMac && laf.contains("Aqua") ? KeyEvent.VK_META : KeyEvent.VK_CONTROL); + } + + private static void mouseTripleClick() { + robot.mousePress(InputEvent.BUTTON1_DOWN_MASK); + robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); + robot.mousePress(InputEvent.BUTTON1_DOWN_MASK); + robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); + robot.mousePress(InputEvent.BUTTON1_DOWN_MASK); + robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); + } + + private static void typeSomeText() { + robot.keyPress(KeyEvent.VK_T); + robot.keyRelease(KeyEvent.VK_T); + robot.keyPress(KeyEvent.VK_E); + robot.keyRelease(KeyEvent.VK_E); + robot.keyPress(KeyEvent.VK_X); + robot.keyRelease(KeyEvent.VK_X); + robot.keyPress(KeyEvent.VK_T); + robot.keyRelease(KeyEvent.VK_T); + } + + private static void createUI() { + frame = new JFrame(); + tree = new JTree(); + tree.setEditable(true); + frame.setContentPane(tree); + frame.setSize(new Dimension(200, 200)); + frame.setAlwaysOnTop(true); + frame.setLocationRelativeTo(null); + frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); + frame.toFront(); + frame.setVisible(true); + } + + private static boolean setLookAndFeel(String lafName) { + try { + UIManager.setLookAndFeel(lafName); + } catch (UnsupportedLookAndFeelException ignored) { + System.out.println("Ignoring Unsupported laf : " + lafName); + return false; + } catch (ClassNotFoundException | InstantiationException + | IllegalAccessException e) { + throw new RuntimeException(e); + } + return true; + } + + private static void disposeFrame() { + if (frame != null) { + frame.dispose(); + frame = null; + } + } + +} diff --git a/test/jdk/javax/swing/JTree/4618767/JTreeSelectedElementTest.java b/test/jdk/javax/swing/JTree/4618767/JTreeSelectedElementTest.java new file mode 100644 index 0000000000000000000000000000000000000000..19b00c05d37570e6b94580c234600b48018bbd97 --- /dev/null +++ b/test/jdk/javax/swing/JTree/4618767/JTreeSelectedElementTest.java @@ -0,0 +1,226 @@ +/* + * 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 + * 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.Point; +import java.awt.Rectangle; +import java.awt.Robot; +import java.awt.event.InputEvent; +import java.awt.event.KeyEvent; +import java.util.Arrays; +import java.util.List; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicReference; +import java.util.stream.Collectors; +import javax.swing.JFrame; +import javax.swing.JMenu; +import javax.swing.JMenuBar; +import javax.swing.JMenuItem; +import javax.swing.JTree; +import javax.swing.SwingUtilities; +import javax.swing.UIManager; +import javax.swing.UIManager.LookAndFeelInfo; +import javax.swing.UnsupportedLookAndFeelException; +import javax.swing.event.MenuEvent; +import javax.swing.event.MenuListener; + +import static javax.swing.UIManager.getInstalledLookAndFeels; + +/* + * @test + * @key headful + * @bug 4618767 + * @summary This test confirms that typing a letter while a JTree has focus now makes the selection + * not jump to the item whose text starts with that letter if that typed letter is accompanied + * by modifier keys such as ALT or CTRL(eg: ALT+F). + * @run main JTreeSelectedElementTest + */ +public class JTreeSelectedElementTest { + + private static final int FILE_MENU = KeyEvent.VK_F; + private static JFrame frame; + private static JTree tree; + private static Robot robot; + private static CountDownLatch menuSelectedEventLatch; + + public static void main(String[] args) throws Exception { + robot = new Robot(); + robot.setAutoWaitForIdle(true); + robot.setAutoDelay(200); + + final boolean isMac = System.getProperty("os.name") + .toLowerCase() + .contains("os x"); + + List lafs = Arrays.stream(getInstalledLookAndFeels()) + .map(LookAndFeelInfo::getClassName) + .collect(Collectors.toList()); + for (final String laf : lafs) { + menuSelectedEventLatch = new CountDownLatch(1); + try { + AtomicBoolean lafSetSuccess = new AtomicBoolean(false); + SwingUtilities.invokeAndWait(() -> { + lafSetSuccess.set(setLookAndFeel(laf)); + if (lafSetSuccess.get()) { + createUI(); + } + }); + if (!lafSetSuccess.get()) { + continue; + } + robot.waitForIdle(); + + // Select the node named as 'colors' + Point pt = getNodeLocation(1); + robot.mouseMove(pt.x, pt.y); + robot.mousePress(InputEvent.BUTTON1_DOWN_MASK); + robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); + + // Assertion check to verify that the selected node is 'colors' + final String elementSelBefore = getCurrentNodeName(); + if (!"colors".equals(elementSelBefore)) { + throw new RuntimeException("Test failed for " + laf + + " as the tree node selected: " + elementSelBefore + + " is not the expected one 'colors'" + ); + } + + // Now operate Menu using Mnemonics, different key combinations for different OSes. + // For most OSes it's ALT+F; on macOS it's ALT+CNTRL+F except for Nimbus LaF. + if (isMac && !laf.contains("Nimbus")) { + hitKeys(KeyEvent.VK_ALT, KeyEvent.VK_CONTROL, FILE_MENU); + } else { + hitKeys(KeyEvent.VK_ALT, FILE_MENU); + } + + // Wait until the menu got selected. + if (!menuSelectedEventLatch.await(3, TimeUnit.SECONDS)) { + throw new RuntimeException("Waited too long, but can't select menu using mnemonics for " + laf); + } + + hitKeys(KeyEvent.VK_ENTER); + + String elementSelAfter = getCurrentNodeName(); + + // As per the fix of BugID 4618767, the tree element selection should not change + if (!elementSelBefore.equals(elementSelAfter)) { + throw new RuntimeException("Test failed for " + laf + + " as tree.getLastSelectedPathComponent() before: " + elementSelBefore + + " not same as tree.getLastSelectedPathComponent() after pressing Enter: " + + elementSelAfter + ); + } + + System.out.println("Test passed for laf: " + laf); + + } finally { + SwingUtilities.invokeAndWait(JTreeSelectedElementTest::disposeFrame); + } + } + } + + private static void hitKeys(int... keys) { + for (int key : keys) { + robot.keyPress(key); + } + + for (int i = keys.length - 1; i >= 0; i--) { + robot.keyRelease(keys[i]); + } + } + + private static String getCurrentNodeName() throws Exception { + AtomicReference nodeName = new AtomicReference<>(); + SwingUtilities.invokeAndWait(() -> { + nodeName.set(tree.getLastSelectedPathComponent().toString().trim()); + }); + return nodeName.get(); + } + + private static Point getNodeLocation(int rowCount) throws Exception { + AtomicReference treeNodeLoc = new AtomicReference<>(); + SwingUtilities.invokeAndWait(() -> { + final Point locationOnScreen = tree.getLocationOnScreen(); + Rectangle rt = tree.getPathBounds(tree.getPathForRow(rowCount)); + locationOnScreen.translate(rt.x + rt.width / 2, rt.y + rt.height / 2); + treeNodeLoc.set(locationOnScreen); + }); + return treeNodeLoc.get(); + } + + private static void createUI() { + frame = new JFrame(); + tree = new JTree(); + JMenu menu = new JMenu("File"); + menu.setMnemonic(FILE_MENU); + JMenuItem menuItem = new JMenuItem("Dummy"); + menu.add(menuItem); + menu.addMenuListener(new MenuListener() { + @Override + public void menuSelected(MenuEvent e) { + menuSelectedEventLatch.countDown(); + } + + @Override + public void menuDeselected(MenuEvent e) { + } + + @Override + public void menuCanceled(MenuEvent e) { + } + }); + + JMenuBar menuBar = new JMenuBar(); + menuBar.add(menu); + + frame.setJMenuBar(menuBar); + frame.setContentPane(tree); + frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); + frame.pack(); + frame.setAlwaysOnTop(true); + frame.setLocationRelativeTo(null); + frame.setVisible(true); + } + + private static boolean setLookAndFeel(String lafName) { + try { + UIManager.setLookAndFeel(lafName); + } catch (UnsupportedLookAndFeelException ignored) { + System.out.println("Ignoring Unsupported L&F: " + lafName); + return false; + } catch (ClassNotFoundException | InstantiationException + | IllegalAccessException e) { + throw new RuntimeException(e); + } + return true; + } + + private static void disposeFrame() { + if (frame != null) { + frame.dispose(); + frame = null; + } + } + +} diff --git a/test/jdk/jdk/incubator/vector/Byte128VectorTests.java b/test/jdk/jdk/incubator/vector/Byte128VectorTests.java index 22e07e05a06b62f76a7453b38ac6ca1dc6c911b4..e7e97452b1660318177af74aec6a5199a071abe5 100644 --- a/test/jdk/jdk/incubator/vector/Byte128VectorTests.java +++ b/test/jdk/jdk/incubator/vector/Byte128VectorTests.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 @@ -3564,19 +3564,21 @@ public class Byte128VectorTests extends AbstractVectorTest { } @Test(dataProvider = "byteTestOpMaskProvider") - static void IS_DEFAULTMaskedByte128VectorTestsSmokeTest(IntFunction fa, + static void IS_DEFAULTMaskedByte128VectorTests(IntFunction fa, IntFunction fm) { byte[] a = fa.apply(SPECIES.length()); boolean[] mask = fm.apply(SPECIES.length()); VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); - for (int i = 0; i < a.length; i += SPECIES.length()) { - ByteVector av = ByteVector.fromArray(SPECIES, a, i); - VectorMask mv = av.test(VectorOperators.IS_DEFAULT, vmask); + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + ByteVector av = ByteVector.fromArray(SPECIES, a, i); + VectorMask mv = av.test(VectorOperators.IS_DEFAULT, vmask); - // Check results as part of computation. - for (int j = 0; j < SPECIES.length(); j++) { - Assert.assertEquals(mv.laneIsSet(j), vmask.laneIsSet(j) && testIS_DEFAULT(a[i + j])); + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + Assert.assertEquals(mv.laneIsSet(j), vmask.laneIsSet(j) && testIS_DEFAULT(a[i + j])); + } } } } @@ -3602,19 +3604,21 @@ public class Byte128VectorTests extends AbstractVectorTest { } @Test(dataProvider = "byteTestOpMaskProvider") - static void IS_NEGATIVEMaskedByte128VectorTestsSmokeTest(IntFunction fa, + static void IS_NEGATIVEMaskedByte128VectorTests(IntFunction fa, IntFunction fm) { byte[] a = fa.apply(SPECIES.length()); boolean[] mask = fm.apply(SPECIES.length()); VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); - for (int i = 0; i < a.length; i += SPECIES.length()) { - ByteVector av = ByteVector.fromArray(SPECIES, a, i); - VectorMask mv = av.test(VectorOperators.IS_NEGATIVE, vmask); + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + ByteVector av = ByteVector.fromArray(SPECIES, a, i); + VectorMask mv = av.test(VectorOperators.IS_NEGATIVE, vmask); - // Check results as part of computation. - for (int j = 0; j < SPECIES.length(); j++) { - Assert.assertEquals(mv.laneIsSet(j), vmask.laneIsSet(j) && testIS_NEGATIVE(a[i + j])); + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + Assert.assertEquals(mv.laneIsSet(j), vmask.laneIsSet(j) && testIS_NEGATIVE(a[i + j])); + } } } } diff --git a/test/jdk/jdk/incubator/vector/Byte256VectorTests.java b/test/jdk/jdk/incubator/vector/Byte256VectorTests.java index 9a631c4799314c9c06909721068f645fffed96f5..aa14ff55a6d34ccfe224aa3d0c178da71fdcedf8 100644 --- a/test/jdk/jdk/incubator/vector/Byte256VectorTests.java +++ b/test/jdk/jdk/incubator/vector/Byte256VectorTests.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 @@ -3564,19 +3564,21 @@ public class Byte256VectorTests extends AbstractVectorTest { } @Test(dataProvider = "byteTestOpMaskProvider") - static void IS_DEFAULTMaskedByte256VectorTestsSmokeTest(IntFunction fa, + static void IS_DEFAULTMaskedByte256VectorTests(IntFunction fa, IntFunction fm) { byte[] a = fa.apply(SPECIES.length()); boolean[] mask = fm.apply(SPECIES.length()); VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); - for (int i = 0; i < a.length; i += SPECIES.length()) { - ByteVector av = ByteVector.fromArray(SPECIES, a, i); - VectorMask mv = av.test(VectorOperators.IS_DEFAULT, vmask); + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + ByteVector av = ByteVector.fromArray(SPECIES, a, i); + VectorMask mv = av.test(VectorOperators.IS_DEFAULT, vmask); - // Check results as part of computation. - for (int j = 0; j < SPECIES.length(); j++) { - Assert.assertEquals(mv.laneIsSet(j), vmask.laneIsSet(j) && testIS_DEFAULT(a[i + j])); + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + Assert.assertEquals(mv.laneIsSet(j), vmask.laneIsSet(j) && testIS_DEFAULT(a[i + j])); + } } } } @@ -3602,19 +3604,21 @@ public class Byte256VectorTests extends AbstractVectorTest { } @Test(dataProvider = "byteTestOpMaskProvider") - static void IS_NEGATIVEMaskedByte256VectorTestsSmokeTest(IntFunction fa, + static void IS_NEGATIVEMaskedByte256VectorTests(IntFunction fa, IntFunction fm) { byte[] a = fa.apply(SPECIES.length()); boolean[] mask = fm.apply(SPECIES.length()); VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); - for (int i = 0; i < a.length; i += SPECIES.length()) { - ByteVector av = ByteVector.fromArray(SPECIES, a, i); - VectorMask mv = av.test(VectorOperators.IS_NEGATIVE, vmask); + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + ByteVector av = ByteVector.fromArray(SPECIES, a, i); + VectorMask mv = av.test(VectorOperators.IS_NEGATIVE, vmask); - // Check results as part of computation. - for (int j = 0; j < SPECIES.length(); j++) { - Assert.assertEquals(mv.laneIsSet(j), vmask.laneIsSet(j) && testIS_NEGATIVE(a[i + j])); + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + Assert.assertEquals(mv.laneIsSet(j), vmask.laneIsSet(j) && testIS_NEGATIVE(a[i + j])); + } } } } diff --git a/test/jdk/jdk/incubator/vector/Byte512VectorTests.java b/test/jdk/jdk/incubator/vector/Byte512VectorTests.java index 203f233e4e8699fba1848699ad5c7cc57387c079..c16f5d7d29668c70667b453032d64342fe8e9fe8 100644 --- a/test/jdk/jdk/incubator/vector/Byte512VectorTests.java +++ b/test/jdk/jdk/incubator/vector/Byte512VectorTests.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 @@ -3564,19 +3564,21 @@ public class Byte512VectorTests extends AbstractVectorTest { } @Test(dataProvider = "byteTestOpMaskProvider") - static void IS_DEFAULTMaskedByte512VectorTestsSmokeTest(IntFunction fa, + static void IS_DEFAULTMaskedByte512VectorTests(IntFunction fa, IntFunction fm) { byte[] a = fa.apply(SPECIES.length()); boolean[] mask = fm.apply(SPECIES.length()); VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); - for (int i = 0; i < a.length; i += SPECIES.length()) { - ByteVector av = ByteVector.fromArray(SPECIES, a, i); - VectorMask mv = av.test(VectorOperators.IS_DEFAULT, vmask); + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + ByteVector av = ByteVector.fromArray(SPECIES, a, i); + VectorMask mv = av.test(VectorOperators.IS_DEFAULT, vmask); - // Check results as part of computation. - for (int j = 0; j < SPECIES.length(); j++) { - Assert.assertEquals(mv.laneIsSet(j), vmask.laneIsSet(j) && testIS_DEFAULT(a[i + j])); + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + Assert.assertEquals(mv.laneIsSet(j), vmask.laneIsSet(j) && testIS_DEFAULT(a[i + j])); + } } } } @@ -3602,19 +3604,21 @@ public class Byte512VectorTests extends AbstractVectorTest { } @Test(dataProvider = "byteTestOpMaskProvider") - static void IS_NEGATIVEMaskedByte512VectorTestsSmokeTest(IntFunction fa, + static void IS_NEGATIVEMaskedByte512VectorTests(IntFunction fa, IntFunction fm) { byte[] a = fa.apply(SPECIES.length()); boolean[] mask = fm.apply(SPECIES.length()); VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); - for (int i = 0; i < a.length; i += SPECIES.length()) { - ByteVector av = ByteVector.fromArray(SPECIES, a, i); - VectorMask mv = av.test(VectorOperators.IS_NEGATIVE, vmask); + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + ByteVector av = ByteVector.fromArray(SPECIES, a, i); + VectorMask mv = av.test(VectorOperators.IS_NEGATIVE, vmask); - // Check results as part of computation. - for (int j = 0; j < SPECIES.length(); j++) { - Assert.assertEquals(mv.laneIsSet(j), vmask.laneIsSet(j) && testIS_NEGATIVE(a[i + j])); + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + Assert.assertEquals(mv.laneIsSet(j), vmask.laneIsSet(j) && testIS_NEGATIVE(a[i + j])); + } } } } diff --git a/test/jdk/jdk/incubator/vector/Byte64VectorTests.java b/test/jdk/jdk/incubator/vector/Byte64VectorTests.java index 110e741ea433883d1e15af28b5d27de3d58a59ef..b47c7be7ed7e441c7f380d03f9178188990a480d 100644 --- a/test/jdk/jdk/incubator/vector/Byte64VectorTests.java +++ b/test/jdk/jdk/incubator/vector/Byte64VectorTests.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 @@ -3564,19 +3564,21 @@ public class Byte64VectorTests extends AbstractVectorTest { } @Test(dataProvider = "byteTestOpMaskProvider") - static void IS_DEFAULTMaskedByte64VectorTestsSmokeTest(IntFunction fa, + static void IS_DEFAULTMaskedByte64VectorTests(IntFunction fa, IntFunction fm) { byte[] a = fa.apply(SPECIES.length()); boolean[] mask = fm.apply(SPECIES.length()); VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); - for (int i = 0; i < a.length; i += SPECIES.length()) { - ByteVector av = ByteVector.fromArray(SPECIES, a, i); - VectorMask mv = av.test(VectorOperators.IS_DEFAULT, vmask); + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + ByteVector av = ByteVector.fromArray(SPECIES, a, i); + VectorMask mv = av.test(VectorOperators.IS_DEFAULT, vmask); - // Check results as part of computation. - for (int j = 0; j < SPECIES.length(); j++) { - Assert.assertEquals(mv.laneIsSet(j), vmask.laneIsSet(j) && testIS_DEFAULT(a[i + j])); + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + Assert.assertEquals(mv.laneIsSet(j), vmask.laneIsSet(j) && testIS_DEFAULT(a[i + j])); + } } } } @@ -3602,19 +3604,21 @@ public class Byte64VectorTests extends AbstractVectorTest { } @Test(dataProvider = "byteTestOpMaskProvider") - static void IS_NEGATIVEMaskedByte64VectorTestsSmokeTest(IntFunction fa, + static void IS_NEGATIVEMaskedByte64VectorTests(IntFunction fa, IntFunction fm) { byte[] a = fa.apply(SPECIES.length()); boolean[] mask = fm.apply(SPECIES.length()); VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); - for (int i = 0; i < a.length; i += SPECIES.length()) { - ByteVector av = ByteVector.fromArray(SPECIES, a, i); - VectorMask mv = av.test(VectorOperators.IS_NEGATIVE, vmask); + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + ByteVector av = ByteVector.fromArray(SPECIES, a, i); + VectorMask mv = av.test(VectorOperators.IS_NEGATIVE, vmask); - // Check results as part of computation. - for (int j = 0; j < SPECIES.length(); j++) { - Assert.assertEquals(mv.laneIsSet(j), vmask.laneIsSet(j) && testIS_NEGATIVE(a[i + j])); + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + Assert.assertEquals(mv.laneIsSet(j), vmask.laneIsSet(j) && testIS_NEGATIVE(a[i + j])); + } } } } diff --git a/test/jdk/jdk/incubator/vector/ByteMaxVectorTests.java b/test/jdk/jdk/incubator/vector/ByteMaxVectorTests.java index e4a9ebf19f5f1a973d849042064378eeae19ca09..7499c29fd50926e6fe0422c0dd250cf792ba6012 100644 --- a/test/jdk/jdk/incubator/vector/ByteMaxVectorTests.java +++ b/test/jdk/jdk/incubator/vector/ByteMaxVectorTests.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 @@ -3569,19 +3569,21 @@ public class ByteMaxVectorTests extends AbstractVectorTest { } @Test(dataProvider = "byteTestOpMaskProvider") - static void IS_DEFAULTMaskedByteMaxVectorTestsSmokeTest(IntFunction fa, + static void IS_DEFAULTMaskedByteMaxVectorTests(IntFunction fa, IntFunction fm) { byte[] a = fa.apply(SPECIES.length()); boolean[] mask = fm.apply(SPECIES.length()); VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); - for (int i = 0; i < a.length; i += SPECIES.length()) { - ByteVector av = ByteVector.fromArray(SPECIES, a, i); - VectorMask mv = av.test(VectorOperators.IS_DEFAULT, vmask); + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + ByteVector av = ByteVector.fromArray(SPECIES, a, i); + VectorMask mv = av.test(VectorOperators.IS_DEFAULT, vmask); - // Check results as part of computation. - for (int j = 0; j < SPECIES.length(); j++) { - Assert.assertEquals(mv.laneIsSet(j), vmask.laneIsSet(j) && testIS_DEFAULT(a[i + j])); + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + Assert.assertEquals(mv.laneIsSet(j), vmask.laneIsSet(j) && testIS_DEFAULT(a[i + j])); + } } } } @@ -3607,19 +3609,21 @@ public class ByteMaxVectorTests extends AbstractVectorTest { } @Test(dataProvider = "byteTestOpMaskProvider") - static void IS_NEGATIVEMaskedByteMaxVectorTestsSmokeTest(IntFunction fa, + static void IS_NEGATIVEMaskedByteMaxVectorTests(IntFunction fa, IntFunction fm) { byte[] a = fa.apply(SPECIES.length()); boolean[] mask = fm.apply(SPECIES.length()); VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); - for (int i = 0; i < a.length; i += SPECIES.length()) { - ByteVector av = ByteVector.fromArray(SPECIES, a, i); - VectorMask mv = av.test(VectorOperators.IS_NEGATIVE, vmask); + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + ByteVector av = ByteVector.fromArray(SPECIES, a, i); + VectorMask mv = av.test(VectorOperators.IS_NEGATIVE, vmask); - // Check results as part of computation. - for (int j = 0; j < SPECIES.length(); j++) { - Assert.assertEquals(mv.laneIsSet(j), vmask.laneIsSet(j) && testIS_NEGATIVE(a[i + j])); + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + Assert.assertEquals(mv.laneIsSet(j), vmask.laneIsSet(j) && testIS_NEGATIVE(a[i + j])); + } } } } diff --git a/test/jdk/jdk/incubator/vector/Double128VectorTests.java b/test/jdk/jdk/incubator/vector/Double128VectorTests.java index c79b1e2f4ef2f277b3d1411b933d966f23d09921..15a55af00c0762964b9d08b2781c6ce07c113601 100644 --- a/test/jdk/jdk/incubator/vector/Double128VectorTests.java +++ b/test/jdk/jdk/incubator/vector/Double128VectorTests.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 @@ -2577,19 +2577,21 @@ public class Double128VectorTests extends AbstractVectorTest { } @Test(dataProvider = "doubleTestOpMaskProvider") - static void IS_DEFAULTMaskedDouble128VectorTestsSmokeTest(IntFunction fa, + static void IS_DEFAULTMaskedDouble128VectorTests(IntFunction fa, IntFunction fm) { double[] a = fa.apply(SPECIES.length()); boolean[] mask = fm.apply(SPECIES.length()); VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); - for (int i = 0; i < a.length; i += SPECIES.length()) { - DoubleVector av = DoubleVector.fromArray(SPECIES, a, i); - VectorMask mv = av.test(VectorOperators.IS_DEFAULT, vmask); + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + DoubleVector av = DoubleVector.fromArray(SPECIES, a, i); + VectorMask mv = av.test(VectorOperators.IS_DEFAULT, vmask); - // Check results as part of computation. - for (int j = 0; j < SPECIES.length(); j++) { - Assert.assertEquals(mv.laneIsSet(j), vmask.laneIsSet(j) && testIS_DEFAULT(a[i + j])); + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + Assert.assertEquals(mv.laneIsSet(j), vmask.laneIsSet(j) && testIS_DEFAULT(a[i + j])); + } } } } @@ -2615,19 +2617,21 @@ public class Double128VectorTests extends AbstractVectorTest { } @Test(dataProvider = "doubleTestOpMaskProvider") - static void IS_NEGATIVEMaskedDouble128VectorTestsSmokeTest(IntFunction fa, + static void IS_NEGATIVEMaskedDouble128VectorTests(IntFunction fa, IntFunction fm) { double[] a = fa.apply(SPECIES.length()); boolean[] mask = fm.apply(SPECIES.length()); VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); - for (int i = 0; i < a.length; i += SPECIES.length()) { - DoubleVector av = DoubleVector.fromArray(SPECIES, a, i); - VectorMask mv = av.test(VectorOperators.IS_NEGATIVE, vmask); + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + DoubleVector av = DoubleVector.fromArray(SPECIES, a, i); + VectorMask mv = av.test(VectorOperators.IS_NEGATIVE, vmask); - // Check results as part of computation. - for (int j = 0; j < SPECIES.length(); j++) { - Assert.assertEquals(mv.laneIsSet(j), vmask.laneIsSet(j) && testIS_NEGATIVE(a[i + j])); + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + Assert.assertEquals(mv.laneIsSet(j), vmask.laneIsSet(j) && testIS_NEGATIVE(a[i + j])); + } } } } @@ -2654,19 +2658,21 @@ public class Double128VectorTests extends AbstractVectorTest { } @Test(dataProvider = "doubleTestOpMaskProvider") - static void IS_FINITEMaskedDouble128VectorTestsSmokeTest(IntFunction fa, + static void IS_FINITEMaskedDouble128VectorTests(IntFunction fa, IntFunction fm) { double[] a = fa.apply(SPECIES.length()); boolean[] mask = fm.apply(SPECIES.length()); VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); - for (int i = 0; i < a.length; i += SPECIES.length()) { - DoubleVector av = DoubleVector.fromArray(SPECIES, a, i); - VectorMask mv = av.test(VectorOperators.IS_FINITE, vmask); + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + DoubleVector av = DoubleVector.fromArray(SPECIES, a, i); + VectorMask mv = av.test(VectorOperators.IS_FINITE, vmask); - // Check results as part of computation. - for (int j = 0; j < SPECIES.length(); j++) { - Assert.assertEquals(mv.laneIsSet(j), vmask.laneIsSet(j) && testIS_FINITE(a[i + j])); + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + Assert.assertEquals(mv.laneIsSet(j), vmask.laneIsSet(j) && testIS_FINITE(a[i + j])); + } } } } @@ -2694,19 +2700,21 @@ public class Double128VectorTests extends AbstractVectorTest { } @Test(dataProvider = "doubleTestOpMaskProvider") - static void IS_NANMaskedDouble128VectorTestsSmokeTest(IntFunction fa, + static void IS_NANMaskedDouble128VectorTests(IntFunction fa, IntFunction fm) { double[] a = fa.apply(SPECIES.length()); boolean[] mask = fm.apply(SPECIES.length()); VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); - for (int i = 0; i < a.length; i += SPECIES.length()) { - DoubleVector av = DoubleVector.fromArray(SPECIES, a, i); - VectorMask mv = av.test(VectorOperators.IS_NAN, vmask); + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + DoubleVector av = DoubleVector.fromArray(SPECIES, a, i); + VectorMask mv = av.test(VectorOperators.IS_NAN, vmask); - // Check results as part of computation. - for (int j = 0; j < SPECIES.length(); j++) { - Assert.assertEquals(mv.laneIsSet(j), vmask.laneIsSet(j) && testIS_NAN(a[i + j])); + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + Assert.assertEquals(mv.laneIsSet(j), vmask.laneIsSet(j) && testIS_NAN(a[i + j])); + } } } } @@ -2734,19 +2742,21 @@ public class Double128VectorTests extends AbstractVectorTest { } @Test(dataProvider = "doubleTestOpMaskProvider") - static void IS_INFINITEMaskedDouble128VectorTestsSmokeTest(IntFunction fa, + static void IS_INFINITEMaskedDouble128VectorTests(IntFunction fa, IntFunction fm) { double[] a = fa.apply(SPECIES.length()); boolean[] mask = fm.apply(SPECIES.length()); VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); - for (int i = 0; i < a.length; i += SPECIES.length()) { - DoubleVector av = DoubleVector.fromArray(SPECIES, a, i); - VectorMask mv = av.test(VectorOperators.IS_INFINITE, vmask); + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + DoubleVector av = DoubleVector.fromArray(SPECIES, a, i); + VectorMask mv = av.test(VectorOperators.IS_INFINITE, vmask); - // Check results as part of computation. - for (int j = 0; j < SPECIES.length(); j++) { - Assert.assertEquals(mv.laneIsSet(j), vmask.laneIsSet(j) && testIS_INFINITE(a[i + j])); + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + Assert.assertEquals(mv.laneIsSet(j), vmask.laneIsSet(j) && testIS_INFINITE(a[i + j])); + } } } } diff --git a/test/jdk/jdk/incubator/vector/Double256VectorTests.java b/test/jdk/jdk/incubator/vector/Double256VectorTests.java index 6d459901d1321ccb2db1641fc0523cd92cbca965..6a9e85129c24aae3242e45b6abb6e3860fd53394 100644 --- a/test/jdk/jdk/incubator/vector/Double256VectorTests.java +++ b/test/jdk/jdk/incubator/vector/Double256VectorTests.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 @@ -2577,19 +2577,21 @@ public class Double256VectorTests extends AbstractVectorTest { } @Test(dataProvider = "doubleTestOpMaskProvider") - static void IS_DEFAULTMaskedDouble256VectorTestsSmokeTest(IntFunction fa, + static void IS_DEFAULTMaskedDouble256VectorTests(IntFunction fa, IntFunction fm) { double[] a = fa.apply(SPECIES.length()); boolean[] mask = fm.apply(SPECIES.length()); VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); - for (int i = 0; i < a.length; i += SPECIES.length()) { - DoubleVector av = DoubleVector.fromArray(SPECIES, a, i); - VectorMask mv = av.test(VectorOperators.IS_DEFAULT, vmask); + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + DoubleVector av = DoubleVector.fromArray(SPECIES, a, i); + VectorMask mv = av.test(VectorOperators.IS_DEFAULT, vmask); - // Check results as part of computation. - for (int j = 0; j < SPECIES.length(); j++) { - Assert.assertEquals(mv.laneIsSet(j), vmask.laneIsSet(j) && testIS_DEFAULT(a[i + j])); + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + Assert.assertEquals(mv.laneIsSet(j), vmask.laneIsSet(j) && testIS_DEFAULT(a[i + j])); + } } } } @@ -2615,19 +2617,21 @@ public class Double256VectorTests extends AbstractVectorTest { } @Test(dataProvider = "doubleTestOpMaskProvider") - static void IS_NEGATIVEMaskedDouble256VectorTestsSmokeTest(IntFunction fa, + static void IS_NEGATIVEMaskedDouble256VectorTests(IntFunction fa, IntFunction fm) { double[] a = fa.apply(SPECIES.length()); boolean[] mask = fm.apply(SPECIES.length()); VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); - for (int i = 0; i < a.length; i += SPECIES.length()) { - DoubleVector av = DoubleVector.fromArray(SPECIES, a, i); - VectorMask mv = av.test(VectorOperators.IS_NEGATIVE, vmask); + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + DoubleVector av = DoubleVector.fromArray(SPECIES, a, i); + VectorMask mv = av.test(VectorOperators.IS_NEGATIVE, vmask); - // Check results as part of computation. - for (int j = 0; j < SPECIES.length(); j++) { - Assert.assertEquals(mv.laneIsSet(j), vmask.laneIsSet(j) && testIS_NEGATIVE(a[i + j])); + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + Assert.assertEquals(mv.laneIsSet(j), vmask.laneIsSet(j) && testIS_NEGATIVE(a[i + j])); + } } } } @@ -2654,19 +2658,21 @@ public class Double256VectorTests extends AbstractVectorTest { } @Test(dataProvider = "doubleTestOpMaskProvider") - static void IS_FINITEMaskedDouble256VectorTestsSmokeTest(IntFunction fa, + static void IS_FINITEMaskedDouble256VectorTests(IntFunction fa, IntFunction fm) { double[] a = fa.apply(SPECIES.length()); boolean[] mask = fm.apply(SPECIES.length()); VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); - for (int i = 0; i < a.length; i += SPECIES.length()) { - DoubleVector av = DoubleVector.fromArray(SPECIES, a, i); - VectorMask mv = av.test(VectorOperators.IS_FINITE, vmask); + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + DoubleVector av = DoubleVector.fromArray(SPECIES, a, i); + VectorMask mv = av.test(VectorOperators.IS_FINITE, vmask); - // Check results as part of computation. - for (int j = 0; j < SPECIES.length(); j++) { - Assert.assertEquals(mv.laneIsSet(j), vmask.laneIsSet(j) && testIS_FINITE(a[i + j])); + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + Assert.assertEquals(mv.laneIsSet(j), vmask.laneIsSet(j) && testIS_FINITE(a[i + j])); + } } } } @@ -2694,19 +2700,21 @@ public class Double256VectorTests extends AbstractVectorTest { } @Test(dataProvider = "doubleTestOpMaskProvider") - static void IS_NANMaskedDouble256VectorTestsSmokeTest(IntFunction fa, + static void IS_NANMaskedDouble256VectorTests(IntFunction fa, IntFunction fm) { double[] a = fa.apply(SPECIES.length()); boolean[] mask = fm.apply(SPECIES.length()); VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); - for (int i = 0; i < a.length; i += SPECIES.length()) { - DoubleVector av = DoubleVector.fromArray(SPECIES, a, i); - VectorMask mv = av.test(VectorOperators.IS_NAN, vmask); + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + DoubleVector av = DoubleVector.fromArray(SPECIES, a, i); + VectorMask mv = av.test(VectorOperators.IS_NAN, vmask); - // Check results as part of computation. - for (int j = 0; j < SPECIES.length(); j++) { - Assert.assertEquals(mv.laneIsSet(j), vmask.laneIsSet(j) && testIS_NAN(a[i + j])); + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + Assert.assertEquals(mv.laneIsSet(j), vmask.laneIsSet(j) && testIS_NAN(a[i + j])); + } } } } @@ -2734,19 +2742,21 @@ public class Double256VectorTests extends AbstractVectorTest { } @Test(dataProvider = "doubleTestOpMaskProvider") - static void IS_INFINITEMaskedDouble256VectorTestsSmokeTest(IntFunction fa, + static void IS_INFINITEMaskedDouble256VectorTests(IntFunction fa, IntFunction fm) { double[] a = fa.apply(SPECIES.length()); boolean[] mask = fm.apply(SPECIES.length()); VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); - for (int i = 0; i < a.length; i += SPECIES.length()) { - DoubleVector av = DoubleVector.fromArray(SPECIES, a, i); - VectorMask mv = av.test(VectorOperators.IS_INFINITE, vmask); + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + DoubleVector av = DoubleVector.fromArray(SPECIES, a, i); + VectorMask mv = av.test(VectorOperators.IS_INFINITE, vmask); - // Check results as part of computation. - for (int j = 0; j < SPECIES.length(); j++) { - Assert.assertEquals(mv.laneIsSet(j), vmask.laneIsSet(j) && testIS_INFINITE(a[i + j])); + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + Assert.assertEquals(mv.laneIsSet(j), vmask.laneIsSet(j) && testIS_INFINITE(a[i + j])); + } } } } diff --git a/test/jdk/jdk/incubator/vector/Double512VectorTests.java b/test/jdk/jdk/incubator/vector/Double512VectorTests.java index 82299753e6572845b15cd0e740f9d46844597018..7d6d280d744cb6c7f0115ddee880d86994af17a4 100644 --- a/test/jdk/jdk/incubator/vector/Double512VectorTests.java +++ b/test/jdk/jdk/incubator/vector/Double512VectorTests.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 @@ -2577,19 +2577,21 @@ public class Double512VectorTests extends AbstractVectorTest { } @Test(dataProvider = "doubleTestOpMaskProvider") - static void IS_DEFAULTMaskedDouble512VectorTestsSmokeTest(IntFunction fa, + static void IS_DEFAULTMaskedDouble512VectorTests(IntFunction fa, IntFunction fm) { double[] a = fa.apply(SPECIES.length()); boolean[] mask = fm.apply(SPECIES.length()); VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); - for (int i = 0; i < a.length; i += SPECIES.length()) { - DoubleVector av = DoubleVector.fromArray(SPECIES, a, i); - VectorMask mv = av.test(VectorOperators.IS_DEFAULT, vmask); + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + DoubleVector av = DoubleVector.fromArray(SPECIES, a, i); + VectorMask mv = av.test(VectorOperators.IS_DEFAULT, vmask); - // Check results as part of computation. - for (int j = 0; j < SPECIES.length(); j++) { - Assert.assertEquals(mv.laneIsSet(j), vmask.laneIsSet(j) && testIS_DEFAULT(a[i + j])); + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + Assert.assertEquals(mv.laneIsSet(j), vmask.laneIsSet(j) && testIS_DEFAULT(a[i + j])); + } } } } @@ -2615,19 +2617,21 @@ public class Double512VectorTests extends AbstractVectorTest { } @Test(dataProvider = "doubleTestOpMaskProvider") - static void IS_NEGATIVEMaskedDouble512VectorTestsSmokeTest(IntFunction fa, + static void IS_NEGATIVEMaskedDouble512VectorTests(IntFunction fa, IntFunction fm) { double[] a = fa.apply(SPECIES.length()); boolean[] mask = fm.apply(SPECIES.length()); VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); - for (int i = 0; i < a.length; i += SPECIES.length()) { - DoubleVector av = DoubleVector.fromArray(SPECIES, a, i); - VectorMask mv = av.test(VectorOperators.IS_NEGATIVE, vmask); + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + DoubleVector av = DoubleVector.fromArray(SPECIES, a, i); + VectorMask mv = av.test(VectorOperators.IS_NEGATIVE, vmask); - // Check results as part of computation. - for (int j = 0; j < SPECIES.length(); j++) { - Assert.assertEquals(mv.laneIsSet(j), vmask.laneIsSet(j) && testIS_NEGATIVE(a[i + j])); + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + Assert.assertEquals(mv.laneIsSet(j), vmask.laneIsSet(j) && testIS_NEGATIVE(a[i + j])); + } } } } @@ -2654,19 +2658,21 @@ public class Double512VectorTests extends AbstractVectorTest { } @Test(dataProvider = "doubleTestOpMaskProvider") - static void IS_FINITEMaskedDouble512VectorTestsSmokeTest(IntFunction fa, + static void IS_FINITEMaskedDouble512VectorTests(IntFunction fa, IntFunction fm) { double[] a = fa.apply(SPECIES.length()); boolean[] mask = fm.apply(SPECIES.length()); VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); - for (int i = 0; i < a.length; i += SPECIES.length()) { - DoubleVector av = DoubleVector.fromArray(SPECIES, a, i); - VectorMask mv = av.test(VectorOperators.IS_FINITE, vmask); + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + DoubleVector av = DoubleVector.fromArray(SPECIES, a, i); + VectorMask mv = av.test(VectorOperators.IS_FINITE, vmask); - // Check results as part of computation. - for (int j = 0; j < SPECIES.length(); j++) { - Assert.assertEquals(mv.laneIsSet(j), vmask.laneIsSet(j) && testIS_FINITE(a[i + j])); + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + Assert.assertEquals(mv.laneIsSet(j), vmask.laneIsSet(j) && testIS_FINITE(a[i + j])); + } } } } @@ -2694,19 +2700,21 @@ public class Double512VectorTests extends AbstractVectorTest { } @Test(dataProvider = "doubleTestOpMaskProvider") - static void IS_NANMaskedDouble512VectorTestsSmokeTest(IntFunction fa, + static void IS_NANMaskedDouble512VectorTests(IntFunction fa, IntFunction fm) { double[] a = fa.apply(SPECIES.length()); boolean[] mask = fm.apply(SPECIES.length()); VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); - for (int i = 0; i < a.length; i += SPECIES.length()) { - DoubleVector av = DoubleVector.fromArray(SPECIES, a, i); - VectorMask mv = av.test(VectorOperators.IS_NAN, vmask); + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + DoubleVector av = DoubleVector.fromArray(SPECIES, a, i); + VectorMask mv = av.test(VectorOperators.IS_NAN, vmask); - // Check results as part of computation. - for (int j = 0; j < SPECIES.length(); j++) { - Assert.assertEquals(mv.laneIsSet(j), vmask.laneIsSet(j) && testIS_NAN(a[i + j])); + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + Assert.assertEquals(mv.laneIsSet(j), vmask.laneIsSet(j) && testIS_NAN(a[i + j])); + } } } } @@ -2734,19 +2742,21 @@ public class Double512VectorTests extends AbstractVectorTest { } @Test(dataProvider = "doubleTestOpMaskProvider") - static void IS_INFINITEMaskedDouble512VectorTestsSmokeTest(IntFunction fa, + static void IS_INFINITEMaskedDouble512VectorTests(IntFunction fa, IntFunction fm) { double[] a = fa.apply(SPECIES.length()); boolean[] mask = fm.apply(SPECIES.length()); VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); - for (int i = 0; i < a.length; i += SPECIES.length()) { - DoubleVector av = DoubleVector.fromArray(SPECIES, a, i); - VectorMask mv = av.test(VectorOperators.IS_INFINITE, vmask); + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + DoubleVector av = DoubleVector.fromArray(SPECIES, a, i); + VectorMask mv = av.test(VectorOperators.IS_INFINITE, vmask); - // Check results as part of computation. - for (int j = 0; j < SPECIES.length(); j++) { - Assert.assertEquals(mv.laneIsSet(j), vmask.laneIsSet(j) && testIS_INFINITE(a[i + j])); + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + Assert.assertEquals(mv.laneIsSet(j), vmask.laneIsSet(j) && testIS_INFINITE(a[i + j])); + } } } } diff --git a/test/jdk/jdk/incubator/vector/Double64VectorTests.java b/test/jdk/jdk/incubator/vector/Double64VectorTests.java index 82fd826ffcb60094681aa5d053006b91256bf980..35bf2ec0465fe2813e52200f1701300a313ec509 100644 --- a/test/jdk/jdk/incubator/vector/Double64VectorTests.java +++ b/test/jdk/jdk/incubator/vector/Double64VectorTests.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 @@ -2577,19 +2577,21 @@ public class Double64VectorTests extends AbstractVectorTest { } @Test(dataProvider = "doubleTestOpMaskProvider") - static void IS_DEFAULTMaskedDouble64VectorTestsSmokeTest(IntFunction fa, + static void IS_DEFAULTMaskedDouble64VectorTests(IntFunction fa, IntFunction fm) { double[] a = fa.apply(SPECIES.length()); boolean[] mask = fm.apply(SPECIES.length()); VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); - for (int i = 0; i < a.length; i += SPECIES.length()) { - DoubleVector av = DoubleVector.fromArray(SPECIES, a, i); - VectorMask mv = av.test(VectorOperators.IS_DEFAULT, vmask); + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + DoubleVector av = DoubleVector.fromArray(SPECIES, a, i); + VectorMask mv = av.test(VectorOperators.IS_DEFAULT, vmask); - // Check results as part of computation. - for (int j = 0; j < SPECIES.length(); j++) { - Assert.assertEquals(mv.laneIsSet(j), vmask.laneIsSet(j) && testIS_DEFAULT(a[i + j])); + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + Assert.assertEquals(mv.laneIsSet(j), vmask.laneIsSet(j) && testIS_DEFAULT(a[i + j])); + } } } } @@ -2615,19 +2617,21 @@ public class Double64VectorTests extends AbstractVectorTest { } @Test(dataProvider = "doubleTestOpMaskProvider") - static void IS_NEGATIVEMaskedDouble64VectorTestsSmokeTest(IntFunction fa, + static void IS_NEGATIVEMaskedDouble64VectorTests(IntFunction fa, IntFunction fm) { double[] a = fa.apply(SPECIES.length()); boolean[] mask = fm.apply(SPECIES.length()); VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); - for (int i = 0; i < a.length; i += SPECIES.length()) { - DoubleVector av = DoubleVector.fromArray(SPECIES, a, i); - VectorMask mv = av.test(VectorOperators.IS_NEGATIVE, vmask); + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + DoubleVector av = DoubleVector.fromArray(SPECIES, a, i); + VectorMask mv = av.test(VectorOperators.IS_NEGATIVE, vmask); - // Check results as part of computation. - for (int j = 0; j < SPECIES.length(); j++) { - Assert.assertEquals(mv.laneIsSet(j), vmask.laneIsSet(j) && testIS_NEGATIVE(a[i + j])); + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + Assert.assertEquals(mv.laneIsSet(j), vmask.laneIsSet(j) && testIS_NEGATIVE(a[i + j])); + } } } } @@ -2654,19 +2658,21 @@ public class Double64VectorTests extends AbstractVectorTest { } @Test(dataProvider = "doubleTestOpMaskProvider") - static void IS_FINITEMaskedDouble64VectorTestsSmokeTest(IntFunction fa, + static void IS_FINITEMaskedDouble64VectorTests(IntFunction fa, IntFunction fm) { double[] a = fa.apply(SPECIES.length()); boolean[] mask = fm.apply(SPECIES.length()); VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); - for (int i = 0; i < a.length; i += SPECIES.length()) { - DoubleVector av = DoubleVector.fromArray(SPECIES, a, i); - VectorMask mv = av.test(VectorOperators.IS_FINITE, vmask); + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + DoubleVector av = DoubleVector.fromArray(SPECIES, a, i); + VectorMask mv = av.test(VectorOperators.IS_FINITE, vmask); - // Check results as part of computation. - for (int j = 0; j < SPECIES.length(); j++) { - Assert.assertEquals(mv.laneIsSet(j), vmask.laneIsSet(j) && testIS_FINITE(a[i + j])); + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + Assert.assertEquals(mv.laneIsSet(j), vmask.laneIsSet(j) && testIS_FINITE(a[i + j])); + } } } } @@ -2694,19 +2700,21 @@ public class Double64VectorTests extends AbstractVectorTest { } @Test(dataProvider = "doubleTestOpMaskProvider") - static void IS_NANMaskedDouble64VectorTestsSmokeTest(IntFunction fa, + static void IS_NANMaskedDouble64VectorTests(IntFunction fa, IntFunction fm) { double[] a = fa.apply(SPECIES.length()); boolean[] mask = fm.apply(SPECIES.length()); VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); - for (int i = 0; i < a.length; i += SPECIES.length()) { - DoubleVector av = DoubleVector.fromArray(SPECIES, a, i); - VectorMask mv = av.test(VectorOperators.IS_NAN, vmask); + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + DoubleVector av = DoubleVector.fromArray(SPECIES, a, i); + VectorMask mv = av.test(VectorOperators.IS_NAN, vmask); - // Check results as part of computation. - for (int j = 0; j < SPECIES.length(); j++) { - Assert.assertEquals(mv.laneIsSet(j), vmask.laneIsSet(j) && testIS_NAN(a[i + j])); + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + Assert.assertEquals(mv.laneIsSet(j), vmask.laneIsSet(j) && testIS_NAN(a[i + j])); + } } } } @@ -2734,19 +2742,21 @@ public class Double64VectorTests extends AbstractVectorTest { } @Test(dataProvider = "doubleTestOpMaskProvider") - static void IS_INFINITEMaskedDouble64VectorTestsSmokeTest(IntFunction fa, + static void IS_INFINITEMaskedDouble64VectorTests(IntFunction fa, IntFunction fm) { double[] a = fa.apply(SPECIES.length()); boolean[] mask = fm.apply(SPECIES.length()); VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); - for (int i = 0; i < a.length; i += SPECIES.length()) { - DoubleVector av = DoubleVector.fromArray(SPECIES, a, i); - VectorMask mv = av.test(VectorOperators.IS_INFINITE, vmask); + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + DoubleVector av = DoubleVector.fromArray(SPECIES, a, i); + VectorMask mv = av.test(VectorOperators.IS_INFINITE, vmask); - // Check results as part of computation. - for (int j = 0; j < SPECIES.length(); j++) { - Assert.assertEquals(mv.laneIsSet(j), vmask.laneIsSet(j) && testIS_INFINITE(a[i + j])); + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + Assert.assertEquals(mv.laneIsSet(j), vmask.laneIsSet(j) && testIS_INFINITE(a[i + j])); + } } } } diff --git a/test/jdk/jdk/incubator/vector/DoubleMaxVectorTests.java b/test/jdk/jdk/incubator/vector/DoubleMaxVectorTests.java index af9054efbb0273cada52dde2e755486aded38c48..102749b7ca036f29afcbcaf8be54e98b3da75e5c 100644 --- a/test/jdk/jdk/incubator/vector/DoubleMaxVectorTests.java +++ b/test/jdk/jdk/incubator/vector/DoubleMaxVectorTests.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 @@ -2582,19 +2582,21 @@ public class DoubleMaxVectorTests extends AbstractVectorTest { } @Test(dataProvider = "doubleTestOpMaskProvider") - static void IS_DEFAULTMaskedDoubleMaxVectorTestsSmokeTest(IntFunction fa, + static void IS_DEFAULTMaskedDoubleMaxVectorTests(IntFunction fa, IntFunction fm) { double[] a = fa.apply(SPECIES.length()); boolean[] mask = fm.apply(SPECIES.length()); VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); - for (int i = 0; i < a.length; i += SPECIES.length()) { - DoubleVector av = DoubleVector.fromArray(SPECIES, a, i); - VectorMask mv = av.test(VectorOperators.IS_DEFAULT, vmask); + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + DoubleVector av = DoubleVector.fromArray(SPECIES, a, i); + VectorMask mv = av.test(VectorOperators.IS_DEFAULT, vmask); - // Check results as part of computation. - for (int j = 0; j < SPECIES.length(); j++) { - Assert.assertEquals(mv.laneIsSet(j), vmask.laneIsSet(j) && testIS_DEFAULT(a[i + j])); + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + Assert.assertEquals(mv.laneIsSet(j), vmask.laneIsSet(j) && testIS_DEFAULT(a[i + j])); + } } } } @@ -2620,19 +2622,21 @@ public class DoubleMaxVectorTests extends AbstractVectorTest { } @Test(dataProvider = "doubleTestOpMaskProvider") - static void IS_NEGATIVEMaskedDoubleMaxVectorTestsSmokeTest(IntFunction fa, + static void IS_NEGATIVEMaskedDoubleMaxVectorTests(IntFunction fa, IntFunction fm) { double[] a = fa.apply(SPECIES.length()); boolean[] mask = fm.apply(SPECIES.length()); VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); - for (int i = 0; i < a.length; i += SPECIES.length()) { - DoubleVector av = DoubleVector.fromArray(SPECIES, a, i); - VectorMask mv = av.test(VectorOperators.IS_NEGATIVE, vmask); + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + DoubleVector av = DoubleVector.fromArray(SPECIES, a, i); + VectorMask mv = av.test(VectorOperators.IS_NEGATIVE, vmask); - // Check results as part of computation. - for (int j = 0; j < SPECIES.length(); j++) { - Assert.assertEquals(mv.laneIsSet(j), vmask.laneIsSet(j) && testIS_NEGATIVE(a[i + j])); + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + Assert.assertEquals(mv.laneIsSet(j), vmask.laneIsSet(j) && testIS_NEGATIVE(a[i + j])); + } } } } @@ -2659,19 +2663,21 @@ public class DoubleMaxVectorTests extends AbstractVectorTest { } @Test(dataProvider = "doubleTestOpMaskProvider") - static void IS_FINITEMaskedDoubleMaxVectorTestsSmokeTest(IntFunction fa, + static void IS_FINITEMaskedDoubleMaxVectorTests(IntFunction fa, IntFunction fm) { double[] a = fa.apply(SPECIES.length()); boolean[] mask = fm.apply(SPECIES.length()); VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); - for (int i = 0; i < a.length; i += SPECIES.length()) { - DoubleVector av = DoubleVector.fromArray(SPECIES, a, i); - VectorMask mv = av.test(VectorOperators.IS_FINITE, vmask); + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + DoubleVector av = DoubleVector.fromArray(SPECIES, a, i); + VectorMask mv = av.test(VectorOperators.IS_FINITE, vmask); - // Check results as part of computation. - for (int j = 0; j < SPECIES.length(); j++) { - Assert.assertEquals(mv.laneIsSet(j), vmask.laneIsSet(j) && testIS_FINITE(a[i + j])); + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + Assert.assertEquals(mv.laneIsSet(j), vmask.laneIsSet(j) && testIS_FINITE(a[i + j])); + } } } } @@ -2699,19 +2705,21 @@ public class DoubleMaxVectorTests extends AbstractVectorTest { } @Test(dataProvider = "doubleTestOpMaskProvider") - static void IS_NANMaskedDoubleMaxVectorTestsSmokeTest(IntFunction fa, + static void IS_NANMaskedDoubleMaxVectorTests(IntFunction fa, IntFunction fm) { double[] a = fa.apply(SPECIES.length()); boolean[] mask = fm.apply(SPECIES.length()); VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); - for (int i = 0; i < a.length; i += SPECIES.length()) { - DoubleVector av = DoubleVector.fromArray(SPECIES, a, i); - VectorMask mv = av.test(VectorOperators.IS_NAN, vmask); + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + DoubleVector av = DoubleVector.fromArray(SPECIES, a, i); + VectorMask mv = av.test(VectorOperators.IS_NAN, vmask); - // Check results as part of computation. - for (int j = 0; j < SPECIES.length(); j++) { - Assert.assertEquals(mv.laneIsSet(j), vmask.laneIsSet(j) && testIS_NAN(a[i + j])); + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + Assert.assertEquals(mv.laneIsSet(j), vmask.laneIsSet(j) && testIS_NAN(a[i + j])); + } } } } @@ -2739,19 +2747,21 @@ public class DoubleMaxVectorTests extends AbstractVectorTest { } @Test(dataProvider = "doubleTestOpMaskProvider") - static void IS_INFINITEMaskedDoubleMaxVectorTestsSmokeTest(IntFunction fa, + static void IS_INFINITEMaskedDoubleMaxVectorTests(IntFunction fa, IntFunction fm) { double[] a = fa.apply(SPECIES.length()); boolean[] mask = fm.apply(SPECIES.length()); VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); - for (int i = 0; i < a.length; i += SPECIES.length()) { - DoubleVector av = DoubleVector.fromArray(SPECIES, a, i); - VectorMask mv = av.test(VectorOperators.IS_INFINITE, vmask); + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + DoubleVector av = DoubleVector.fromArray(SPECIES, a, i); + VectorMask mv = av.test(VectorOperators.IS_INFINITE, vmask); - // Check results as part of computation. - for (int j = 0; j < SPECIES.length(); j++) { - Assert.assertEquals(mv.laneIsSet(j), vmask.laneIsSet(j) && testIS_INFINITE(a[i + j])); + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + Assert.assertEquals(mv.laneIsSet(j), vmask.laneIsSet(j) && testIS_INFINITE(a[i + j])); + } } } } diff --git a/test/jdk/jdk/incubator/vector/Float128VectorTests.java b/test/jdk/jdk/incubator/vector/Float128VectorTests.java index c793515b6c64566a5a1d4b8a73675ddb1d4f52ee..114ac299f3ee557d063331a223cb089b30b2b597 100644 --- a/test/jdk/jdk/incubator/vector/Float128VectorTests.java +++ b/test/jdk/jdk/incubator/vector/Float128VectorTests.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 @@ -2587,19 +2587,21 @@ public class Float128VectorTests extends AbstractVectorTest { } @Test(dataProvider = "floatTestOpMaskProvider") - static void IS_DEFAULTMaskedFloat128VectorTestsSmokeTest(IntFunction fa, + static void IS_DEFAULTMaskedFloat128VectorTests(IntFunction fa, IntFunction fm) { float[] a = fa.apply(SPECIES.length()); boolean[] mask = fm.apply(SPECIES.length()); VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); - for (int i = 0; i < a.length; i += SPECIES.length()) { - FloatVector av = FloatVector.fromArray(SPECIES, a, i); - VectorMask mv = av.test(VectorOperators.IS_DEFAULT, vmask); + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + FloatVector av = FloatVector.fromArray(SPECIES, a, i); + VectorMask mv = av.test(VectorOperators.IS_DEFAULT, vmask); - // Check results as part of computation. - for (int j = 0; j < SPECIES.length(); j++) { - Assert.assertEquals(mv.laneIsSet(j), vmask.laneIsSet(j) && testIS_DEFAULT(a[i + j])); + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + Assert.assertEquals(mv.laneIsSet(j), vmask.laneIsSet(j) && testIS_DEFAULT(a[i + j])); + } } } } @@ -2625,19 +2627,21 @@ public class Float128VectorTests extends AbstractVectorTest { } @Test(dataProvider = "floatTestOpMaskProvider") - static void IS_NEGATIVEMaskedFloat128VectorTestsSmokeTest(IntFunction fa, + static void IS_NEGATIVEMaskedFloat128VectorTests(IntFunction fa, IntFunction fm) { float[] a = fa.apply(SPECIES.length()); boolean[] mask = fm.apply(SPECIES.length()); VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); - for (int i = 0; i < a.length; i += SPECIES.length()) { - FloatVector av = FloatVector.fromArray(SPECIES, a, i); - VectorMask mv = av.test(VectorOperators.IS_NEGATIVE, vmask); + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + FloatVector av = FloatVector.fromArray(SPECIES, a, i); + VectorMask mv = av.test(VectorOperators.IS_NEGATIVE, vmask); - // Check results as part of computation. - for (int j = 0; j < SPECIES.length(); j++) { - Assert.assertEquals(mv.laneIsSet(j), vmask.laneIsSet(j) && testIS_NEGATIVE(a[i + j])); + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + Assert.assertEquals(mv.laneIsSet(j), vmask.laneIsSet(j) && testIS_NEGATIVE(a[i + j])); + } } } } @@ -2664,19 +2668,21 @@ public class Float128VectorTests extends AbstractVectorTest { } @Test(dataProvider = "floatTestOpMaskProvider") - static void IS_FINITEMaskedFloat128VectorTestsSmokeTest(IntFunction fa, + static void IS_FINITEMaskedFloat128VectorTests(IntFunction fa, IntFunction fm) { float[] a = fa.apply(SPECIES.length()); boolean[] mask = fm.apply(SPECIES.length()); VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); - for (int i = 0; i < a.length; i += SPECIES.length()) { - FloatVector av = FloatVector.fromArray(SPECIES, a, i); - VectorMask mv = av.test(VectorOperators.IS_FINITE, vmask); + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + FloatVector av = FloatVector.fromArray(SPECIES, a, i); + VectorMask mv = av.test(VectorOperators.IS_FINITE, vmask); - // Check results as part of computation. - for (int j = 0; j < SPECIES.length(); j++) { - Assert.assertEquals(mv.laneIsSet(j), vmask.laneIsSet(j) && testIS_FINITE(a[i + j])); + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + Assert.assertEquals(mv.laneIsSet(j), vmask.laneIsSet(j) && testIS_FINITE(a[i + j])); + } } } } @@ -2704,19 +2710,21 @@ public class Float128VectorTests extends AbstractVectorTest { } @Test(dataProvider = "floatTestOpMaskProvider") - static void IS_NANMaskedFloat128VectorTestsSmokeTest(IntFunction fa, + static void IS_NANMaskedFloat128VectorTests(IntFunction fa, IntFunction fm) { float[] a = fa.apply(SPECIES.length()); boolean[] mask = fm.apply(SPECIES.length()); VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); - for (int i = 0; i < a.length; i += SPECIES.length()) { - FloatVector av = FloatVector.fromArray(SPECIES, a, i); - VectorMask mv = av.test(VectorOperators.IS_NAN, vmask); + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + FloatVector av = FloatVector.fromArray(SPECIES, a, i); + VectorMask mv = av.test(VectorOperators.IS_NAN, vmask); - // Check results as part of computation. - for (int j = 0; j < SPECIES.length(); j++) { - Assert.assertEquals(mv.laneIsSet(j), vmask.laneIsSet(j) && testIS_NAN(a[i + j])); + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + Assert.assertEquals(mv.laneIsSet(j), vmask.laneIsSet(j) && testIS_NAN(a[i + j])); + } } } } @@ -2744,19 +2752,21 @@ public class Float128VectorTests extends AbstractVectorTest { } @Test(dataProvider = "floatTestOpMaskProvider") - static void IS_INFINITEMaskedFloat128VectorTestsSmokeTest(IntFunction fa, + static void IS_INFINITEMaskedFloat128VectorTests(IntFunction fa, IntFunction fm) { float[] a = fa.apply(SPECIES.length()); boolean[] mask = fm.apply(SPECIES.length()); VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); - for (int i = 0; i < a.length; i += SPECIES.length()) { - FloatVector av = FloatVector.fromArray(SPECIES, a, i); - VectorMask mv = av.test(VectorOperators.IS_INFINITE, vmask); + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + FloatVector av = FloatVector.fromArray(SPECIES, a, i); + VectorMask mv = av.test(VectorOperators.IS_INFINITE, vmask); - // Check results as part of computation. - for (int j = 0; j < SPECIES.length(); j++) { - Assert.assertEquals(mv.laneIsSet(j), vmask.laneIsSet(j) && testIS_INFINITE(a[i + j])); + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + Assert.assertEquals(mv.laneIsSet(j), vmask.laneIsSet(j) && testIS_INFINITE(a[i + j])); + } } } } diff --git a/test/jdk/jdk/incubator/vector/Float256VectorTests.java b/test/jdk/jdk/incubator/vector/Float256VectorTests.java index 61593a8c23a0fb94f51e1a6258f8f25b7745c23d..8011f3a686912b16d02c26f0950d141cb58c7967 100644 --- a/test/jdk/jdk/incubator/vector/Float256VectorTests.java +++ b/test/jdk/jdk/incubator/vector/Float256VectorTests.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 @@ -2587,19 +2587,21 @@ public class Float256VectorTests extends AbstractVectorTest { } @Test(dataProvider = "floatTestOpMaskProvider") - static void IS_DEFAULTMaskedFloat256VectorTestsSmokeTest(IntFunction fa, + static void IS_DEFAULTMaskedFloat256VectorTests(IntFunction fa, IntFunction fm) { float[] a = fa.apply(SPECIES.length()); boolean[] mask = fm.apply(SPECIES.length()); VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); - for (int i = 0; i < a.length; i += SPECIES.length()) { - FloatVector av = FloatVector.fromArray(SPECIES, a, i); - VectorMask mv = av.test(VectorOperators.IS_DEFAULT, vmask); + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + FloatVector av = FloatVector.fromArray(SPECIES, a, i); + VectorMask mv = av.test(VectorOperators.IS_DEFAULT, vmask); - // Check results as part of computation. - for (int j = 0; j < SPECIES.length(); j++) { - Assert.assertEquals(mv.laneIsSet(j), vmask.laneIsSet(j) && testIS_DEFAULT(a[i + j])); + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + Assert.assertEquals(mv.laneIsSet(j), vmask.laneIsSet(j) && testIS_DEFAULT(a[i + j])); + } } } } @@ -2625,19 +2627,21 @@ public class Float256VectorTests extends AbstractVectorTest { } @Test(dataProvider = "floatTestOpMaskProvider") - static void IS_NEGATIVEMaskedFloat256VectorTestsSmokeTest(IntFunction fa, + static void IS_NEGATIVEMaskedFloat256VectorTests(IntFunction fa, IntFunction fm) { float[] a = fa.apply(SPECIES.length()); boolean[] mask = fm.apply(SPECIES.length()); VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); - for (int i = 0; i < a.length; i += SPECIES.length()) { - FloatVector av = FloatVector.fromArray(SPECIES, a, i); - VectorMask mv = av.test(VectorOperators.IS_NEGATIVE, vmask); + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + FloatVector av = FloatVector.fromArray(SPECIES, a, i); + VectorMask mv = av.test(VectorOperators.IS_NEGATIVE, vmask); - // Check results as part of computation. - for (int j = 0; j < SPECIES.length(); j++) { - Assert.assertEquals(mv.laneIsSet(j), vmask.laneIsSet(j) && testIS_NEGATIVE(a[i + j])); + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + Assert.assertEquals(mv.laneIsSet(j), vmask.laneIsSet(j) && testIS_NEGATIVE(a[i + j])); + } } } } @@ -2664,19 +2668,21 @@ public class Float256VectorTests extends AbstractVectorTest { } @Test(dataProvider = "floatTestOpMaskProvider") - static void IS_FINITEMaskedFloat256VectorTestsSmokeTest(IntFunction fa, + static void IS_FINITEMaskedFloat256VectorTests(IntFunction fa, IntFunction fm) { float[] a = fa.apply(SPECIES.length()); boolean[] mask = fm.apply(SPECIES.length()); VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); - for (int i = 0; i < a.length; i += SPECIES.length()) { - FloatVector av = FloatVector.fromArray(SPECIES, a, i); - VectorMask mv = av.test(VectorOperators.IS_FINITE, vmask); + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + FloatVector av = FloatVector.fromArray(SPECIES, a, i); + VectorMask mv = av.test(VectorOperators.IS_FINITE, vmask); - // Check results as part of computation. - for (int j = 0; j < SPECIES.length(); j++) { - Assert.assertEquals(mv.laneIsSet(j), vmask.laneIsSet(j) && testIS_FINITE(a[i + j])); + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + Assert.assertEquals(mv.laneIsSet(j), vmask.laneIsSet(j) && testIS_FINITE(a[i + j])); + } } } } @@ -2704,19 +2710,21 @@ public class Float256VectorTests extends AbstractVectorTest { } @Test(dataProvider = "floatTestOpMaskProvider") - static void IS_NANMaskedFloat256VectorTestsSmokeTest(IntFunction fa, + static void IS_NANMaskedFloat256VectorTests(IntFunction fa, IntFunction fm) { float[] a = fa.apply(SPECIES.length()); boolean[] mask = fm.apply(SPECIES.length()); VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); - for (int i = 0; i < a.length; i += SPECIES.length()) { - FloatVector av = FloatVector.fromArray(SPECIES, a, i); - VectorMask mv = av.test(VectorOperators.IS_NAN, vmask); + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + FloatVector av = FloatVector.fromArray(SPECIES, a, i); + VectorMask mv = av.test(VectorOperators.IS_NAN, vmask); - // Check results as part of computation. - for (int j = 0; j < SPECIES.length(); j++) { - Assert.assertEquals(mv.laneIsSet(j), vmask.laneIsSet(j) && testIS_NAN(a[i + j])); + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + Assert.assertEquals(mv.laneIsSet(j), vmask.laneIsSet(j) && testIS_NAN(a[i + j])); + } } } } @@ -2744,19 +2752,21 @@ public class Float256VectorTests extends AbstractVectorTest { } @Test(dataProvider = "floatTestOpMaskProvider") - static void IS_INFINITEMaskedFloat256VectorTestsSmokeTest(IntFunction fa, + static void IS_INFINITEMaskedFloat256VectorTests(IntFunction fa, IntFunction fm) { float[] a = fa.apply(SPECIES.length()); boolean[] mask = fm.apply(SPECIES.length()); VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); - for (int i = 0; i < a.length; i += SPECIES.length()) { - FloatVector av = FloatVector.fromArray(SPECIES, a, i); - VectorMask mv = av.test(VectorOperators.IS_INFINITE, vmask); + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + FloatVector av = FloatVector.fromArray(SPECIES, a, i); + VectorMask mv = av.test(VectorOperators.IS_INFINITE, vmask); - // Check results as part of computation. - for (int j = 0; j < SPECIES.length(); j++) { - Assert.assertEquals(mv.laneIsSet(j), vmask.laneIsSet(j) && testIS_INFINITE(a[i + j])); + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + Assert.assertEquals(mv.laneIsSet(j), vmask.laneIsSet(j) && testIS_INFINITE(a[i + j])); + } } } } diff --git a/test/jdk/jdk/incubator/vector/Float512VectorTests.java b/test/jdk/jdk/incubator/vector/Float512VectorTests.java index 421338f053cb9e60cf84ddce6398710bcf095521..f6fa6ecc6f0c422774e9cb189806453beac99ac7 100644 --- a/test/jdk/jdk/incubator/vector/Float512VectorTests.java +++ b/test/jdk/jdk/incubator/vector/Float512VectorTests.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 @@ -2587,19 +2587,21 @@ public class Float512VectorTests extends AbstractVectorTest { } @Test(dataProvider = "floatTestOpMaskProvider") - static void IS_DEFAULTMaskedFloat512VectorTestsSmokeTest(IntFunction fa, + static void IS_DEFAULTMaskedFloat512VectorTests(IntFunction fa, IntFunction fm) { float[] a = fa.apply(SPECIES.length()); boolean[] mask = fm.apply(SPECIES.length()); VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); - for (int i = 0; i < a.length; i += SPECIES.length()) { - FloatVector av = FloatVector.fromArray(SPECIES, a, i); - VectorMask mv = av.test(VectorOperators.IS_DEFAULT, vmask); + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + FloatVector av = FloatVector.fromArray(SPECIES, a, i); + VectorMask mv = av.test(VectorOperators.IS_DEFAULT, vmask); - // Check results as part of computation. - for (int j = 0; j < SPECIES.length(); j++) { - Assert.assertEquals(mv.laneIsSet(j), vmask.laneIsSet(j) && testIS_DEFAULT(a[i + j])); + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + Assert.assertEquals(mv.laneIsSet(j), vmask.laneIsSet(j) && testIS_DEFAULT(a[i + j])); + } } } } @@ -2625,19 +2627,21 @@ public class Float512VectorTests extends AbstractVectorTest { } @Test(dataProvider = "floatTestOpMaskProvider") - static void IS_NEGATIVEMaskedFloat512VectorTestsSmokeTest(IntFunction fa, + static void IS_NEGATIVEMaskedFloat512VectorTests(IntFunction fa, IntFunction fm) { float[] a = fa.apply(SPECIES.length()); boolean[] mask = fm.apply(SPECIES.length()); VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); - for (int i = 0; i < a.length; i += SPECIES.length()) { - FloatVector av = FloatVector.fromArray(SPECIES, a, i); - VectorMask mv = av.test(VectorOperators.IS_NEGATIVE, vmask); + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + FloatVector av = FloatVector.fromArray(SPECIES, a, i); + VectorMask mv = av.test(VectorOperators.IS_NEGATIVE, vmask); - // Check results as part of computation. - for (int j = 0; j < SPECIES.length(); j++) { - Assert.assertEquals(mv.laneIsSet(j), vmask.laneIsSet(j) && testIS_NEGATIVE(a[i + j])); + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + Assert.assertEquals(mv.laneIsSet(j), vmask.laneIsSet(j) && testIS_NEGATIVE(a[i + j])); + } } } } @@ -2664,19 +2668,21 @@ public class Float512VectorTests extends AbstractVectorTest { } @Test(dataProvider = "floatTestOpMaskProvider") - static void IS_FINITEMaskedFloat512VectorTestsSmokeTest(IntFunction fa, + static void IS_FINITEMaskedFloat512VectorTests(IntFunction fa, IntFunction fm) { float[] a = fa.apply(SPECIES.length()); boolean[] mask = fm.apply(SPECIES.length()); VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); - for (int i = 0; i < a.length; i += SPECIES.length()) { - FloatVector av = FloatVector.fromArray(SPECIES, a, i); - VectorMask mv = av.test(VectorOperators.IS_FINITE, vmask); + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + FloatVector av = FloatVector.fromArray(SPECIES, a, i); + VectorMask mv = av.test(VectorOperators.IS_FINITE, vmask); - // Check results as part of computation. - for (int j = 0; j < SPECIES.length(); j++) { - Assert.assertEquals(mv.laneIsSet(j), vmask.laneIsSet(j) && testIS_FINITE(a[i + j])); + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + Assert.assertEquals(mv.laneIsSet(j), vmask.laneIsSet(j) && testIS_FINITE(a[i + j])); + } } } } @@ -2704,19 +2710,21 @@ public class Float512VectorTests extends AbstractVectorTest { } @Test(dataProvider = "floatTestOpMaskProvider") - static void IS_NANMaskedFloat512VectorTestsSmokeTest(IntFunction fa, + static void IS_NANMaskedFloat512VectorTests(IntFunction fa, IntFunction fm) { float[] a = fa.apply(SPECIES.length()); boolean[] mask = fm.apply(SPECIES.length()); VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); - for (int i = 0; i < a.length; i += SPECIES.length()) { - FloatVector av = FloatVector.fromArray(SPECIES, a, i); - VectorMask mv = av.test(VectorOperators.IS_NAN, vmask); + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + FloatVector av = FloatVector.fromArray(SPECIES, a, i); + VectorMask mv = av.test(VectorOperators.IS_NAN, vmask); - // Check results as part of computation. - for (int j = 0; j < SPECIES.length(); j++) { - Assert.assertEquals(mv.laneIsSet(j), vmask.laneIsSet(j) && testIS_NAN(a[i + j])); + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + Assert.assertEquals(mv.laneIsSet(j), vmask.laneIsSet(j) && testIS_NAN(a[i + j])); + } } } } @@ -2744,19 +2752,21 @@ public class Float512VectorTests extends AbstractVectorTest { } @Test(dataProvider = "floatTestOpMaskProvider") - static void IS_INFINITEMaskedFloat512VectorTestsSmokeTest(IntFunction fa, + static void IS_INFINITEMaskedFloat512VectorTests(IntFunction fa, IntFunction fm) { float[] a = fa.apply(SPECIES.length()); boolean[] mask = fm.apply(SPECIES.length()); VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); - for (int i = 0; i < a.length; i += SPECIES.length()) { - FloatVector av = FloatVector.fromArray(SPECIES, a, i); - VectorMask mv = av.test(VectorOperators.IS_INFINITE, vmask); + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + FloatVector av = FloatVector.fromArray(SPECIES, a, i); + VectorMask mv = av.test(VectorOperators.IS_INFINITE, vmask); - // Check results as part of computation. - for (int j = 0; j < SPECIES.length(); j++) { - Assert.assertEquals(mv.laneIsSet(j), vmask.laneIsSet(j) && testIS_INFINITE(a[i + j])); + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + Assert.assertEquals(mv.laneIsSet(j), vmask.laneIsSet(j) && testIS_INFINITE(a[i + j])); + } } } } diff --git a/test/jdk/jdk/incubator/vector/Float64VectorTests.java b/test/jdk/jdk/incubator/vector/Float64VectorTests.java index cbe82a7e22da5b351b65f6d45a1ad782be3b88d9..d0edf33f34050aad22461c938d5a09aa4524c55c 100644 --- a/test/jdk/jdk/incubator/vector/Float64VectorTests.java +++ b/test/jdk/jdk/incubator/vector/Float64VectorTests.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 @@ -2587,19 +2587,21 @@ public class Float64VectorTests extends AbstractVectorTest { } @Test(dataProvider = "floatTestOpMaskProvider") - static void IS_DEFAULTMaskedFloat64VectorTestsSmokeTest(IntFunction fa, + static void IS_DEFAULTMaskedFloat64VectorTests(IntFunction fa, IntFunction fm) { float[] a = fa.apply(SPECIES.length()); boolean[] mask = fm.apply(SPECIES.length()); VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); - for (int i = 0; i < a.length; i += SPECIES.length()) { - FloatVector av = FloatVector.fromArray(SPECIES, a, i); - VectorMask mv = av.test(VectorOperators.IS_DEFAULT, vmask); + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + FloatVector av = FloatVector.fromArray(SPECIES, a, i); + VectorMask mv = av.test(VectorOperators.IS_DEFAULT, vmask); - // Check results as part of computation. - for (int j = 0; j < SPECIES.length(); j++) { - Assert.assertEquals(mv.laneIsSet(j), vmask.laneIsSet(j) && testIS_DEFAULT(a[i + j])); + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + Assert.assertEquals(mv.laneIsSet(j), vmask.laneIsSet(j) && testIS_DEFAULT(a[i + j])); + } } } } @@ -2625,19 +2627,21 @@ public class Float64VectorTests extends AbstractVectorTest { } @Test(dataProvider = "floatTestOpMaskProvider") - static void IS_NEGATIVEMaskedFloat64VectorTestsSmokeTest(IntFunction fa, + static void IS_NEGATIVEMaskedFloat64VectorTests(IntFunction fa, IntFunction fm) { float[] a = fa.apply(SPECIES.length()); boolean[] mask = fm.apply(SPECIES.length()); VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); - for (int i = 0; i < a.length; i += SPECIES.length()) { - FloatVector av = FloatVector.fromArray(SPECIES, a, i); - VectorMask mv = av.test(VectorOperators.IS_NEGATIVE, vmask); + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + FloatVector av = FloatVector.fromArray(SPECIES, a, i); + VectorMask mv = av.test(VectorOperators.IS_NEGATIVE, vmask); - // Check results as part of computation. - for (int j = 0; j < SPECIES.length(); j++) { - Assert.assertEquals(mv.laneIsSet(j), vmask.laneIsSet(j) && testIS_NEGATIVE(a[i + j])); + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + Assert.assertEquals(mv.laneIsSet(j), vmask.laneIsSet(j) && testIS_NEGATIVE(a[i + j])); + } } } } @@ -2664,19 +2668,21 @@ public class Float64VectorTests extends AbstractVectorTest { } @Test(dataProvider = "floatTestOpMaskProvider") - static void IS_FINITEMaskedFloat64VectorTestsSmokeTest(IntFunction fa, + static void IS_FINITEMaskedFloat64VectorTests(IntFunction fa, IntFunction fm) { float[] a = fa.apply(SPECIES.length()); boolean[] mask = fm.apply(SPECIES.length()); VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); - for (int i = 0; i < a.length; i += SPECIES.length()) { - FloatVector av = FloatVector.fromArray(SPECIES, a, i); - VectorMask mv = av.test(VectorOperators.IS_FINITE, vmask); + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + FloatVector av = FloatVector.fromArray(SPECIES, a, i); + VectorMask mv = av.test(VectorOperators.IS_FINITE, vmask); - // Check results as part of computation. - for (int j = 0; j < SPECIES.length(); j++) { - Assert.assertEquals(mv.laneIsSet(j), vmask.laneIsSet(j) && testIS_FINITE(a[i + j])); + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + Assert.assertEquals(mv.laneIsSet(j), vmask.laneIsSet(j) && testIS_FINITE(a[i + j])); + } } } } @@ -2704,19 +2710,21 @@ public class Float64VectorTests extends AbstractVectorTest { } @Test(dataProvider = "floatTestOpMaskProvider") - static void IS_NANMaskedFloat64VectorTestsSmokeTest(IntFunction fa, + static void IS_NANMaskedFloat64VectorTests(IntFunction fa, IntFunction fm) { float[] a = fa.apply(SPECIES.length()); boolean[] mask = fm.apply(SPECIES.length()); VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); - for (int i = 0; i < a.length; i += SPECIES.length()) { - FloatVector av = FloatVector.fromArray(SPECIES, a, i); - VectorMask mv = av.test(VectorOperators.IS_NAN, vmask); + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + FloatVector av = FloatVector.fromArray(SPECIES, a, i); + VectorMask mv = av.test(VectorOperators.IS_NAN, vmask); - // Check results as part of computation. - for (int j = 0; j < SPECIES.length(); j++) { - Assert.assertEquals(mv.laneIsSet(j), vmask.laneIsSet(j) && testIS_NAN(a[i + j])); + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + Assert.assertEquals(mv.laneIsSet(j), vmask.laneIsSet(j) && testIS_NAN(a[i + j])); + } } } } @@ -2744,19 +2752,21 @@ public class Float64VectorTests extends AbstractVectorTest { } @Test(dataProvider = "floatTestOpMaskProvider") - static void IS_INFINITEMaskedFloat64VectorTestsSmokeTest(IntFunction fa, + static void IS_INFINITEMaskedFloat64VectorTests(IntFunction fa, IntFunction fm) { float[] a = fa.apply(SPECIES.length()); boolean[] mask = fm.apply(SPECIES.length()); VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); - for (int i = 0; i < a.length; i += SPECIES.length()) { - FloatVector av = FloatVector.fromArray(SPECIES, a, i); - VectorMask mv = av.test(VectorOperators.IS_INFINITE, vmask); + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + FloatVector av = FloatVector.fromArray(SPECIES, a, i); + VectorMask mv = av.test(VectorOperators.IS_INFINITE, vmask); - // Check results as part of computation. - for (int j = 0; j < SPECIES.length(); j++) { - Assert.assertEquals(mv.laneIsSet(j), vmask.laneIsSet(j) && testIS_INFINITE(a[i + j])); + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + Assert.assertEquals(mv.laneIsSet(j), vmask.laneIsSet(j) && testIS_INFINITE(a[i + j])); + } } } } diff --git a/test/jdk/jdk/incubator/vector/FloatMaxVectorTests.java b/test/jdk/jdk/incubator/vector/FloatMaxVectorTests.java index e8680eb1d944947f9fadcdd9c40ed5985fcc887a..4f8711e8b1c9ce03b313286e1b414472f7b6cea6 100644 --- a/test/jdk/jdk/incubator/vector/FloatMaxVectorTests.java +++ b/test/jdk/jdk/incubator/vector/FloatMaxVectorTests.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 @@ -2592,19 +2592,21 @@ public class FloatMaxVectorTests extends AbstractVectorTest { } @Test(dataProvider = "floatTestOpMaskProvider") - static void IS_DEFAULTMaskedFloatMaxVectorTestsSmokeTest(IntFunction fa, + static void IS_DEFAULTMaskedFloatMaxVectorTests(IntFunction fa, IntFunction fm) { float[] a = fa.apply(SPECIES.length()); boolean[] mask = fm.apply(SPECIES.length()); VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); - for (int i = 0; i < a.length; i += SPECIES.length()) { - FloatVector av = FloatVector.fromArray(SPECIES, a, i); - VectorMask mv = av.test(VectorOperators.IS_DEFAULT, vmask); + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + FloatVector av = FloatVector.fromArray(SPECIES, a, i); + VectorMask mv = av.test(VectorOperators.IS_DEFAULT, vmask); - // Check results as part of computation. - for (int j = 0; j < SPECIES.length(); j++) { - Assert.assertEquals(mv.laneIsSet(j), vmask.laneIsSet(j) && testIS_DEFAULT(a[i + j])); + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + Assert.assertEquals(mv.laneIsSet(j), vmask.laneIsSet(j) && testIS_DEFAULT(a[i + j])); + } } } } @@ -2630,19 +2632,21 @@ public class FloatMaxVectorTests extends AbstractVectorTest { } @Test(dataProvider = "floatTestOpMaskProvider") - static void IS_NEGATIVEMaskedFloatMaxVectorTestsSmokeTest(IntFunction fa, + static void IS_NEGATIVEMaskedFloatMaxVectorTests(IntFunction fa, IntFunction fm) { float[] a = fa.apply(SPECIES.length()); boolean[] mask = fm.apply(SPECIES.length()); VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); - for (int i = 0; i < a.length; i += SPECIES.length()) { - FloatVector av = FloatVector.fromArray(SPECIES, a, i); - VectorMask mv = av.test(VectorOperators.IS_NEGATIVE, vmask); + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + FloatVector av = FloatVector.fromArray(SPECIES, a, i); + VectorMask mv = av.test(VectorOperators.IS_NEGATIVE, vmask); - // Check results as part of computation. - for (int j = 0; j < SPECIES.length(); j++) { - Assert.assertEquals(mv.laneIsSet(j), vmask.laneIsSet(j) && testIS_NEGATIVE(a[i + j])); + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + Assert.assertEquals(mv.laneIsSet(j), vmask.laneIsSet(j) && testIS_NEGATIVE(a[i + j])); + } } } } @@ -2669,19 +2673,21 @@ public class FloatMaxVectorTests extends AbstractVectorTest { } @Test(dataProvider = "floatTestOpMaskProvider") - static void IS_FINITEMaskedFloatMaxVectorTestsSmokeTest(IntFunction fa, + static void IS_FINITEMaskedFloatMaxVectorTests(IntFunction fa, IntFunction fm) { float[] a = fa.apply(SPECIES.length()); boolean[] mask = fm.apply(SPECIES.length()); VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); - for (int i = 0; i < a.length; i += SPECIES.length()) { - FloatVector av = FloatVector.fromArray(SPECIES, a, i); - VectorMask mv = av.test(VectorOperators.IS_FINITE, vmask); + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + FloatVector av = FloatVector.fromArray(SPECIES, a, i); + VectorMask mv = av.test(VectorOperators.IS_FINITE, vmask); - // Check results as part of computation. - for (int j = 0; j < SPECIES.length(); j++) { - Assert.assertEquals(mv.laneIsSet(j), vmask.laneIsSet(j) && testIS_FINITE(a[i + j])); + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + Assert.assertEquals(mv.laneIsSet(j), vmask.laneIsSet(j) && testIS_FINITE(a[i + j])); + } } } } @@ -2709,19 +2715,21 @@ public class FloatMaxVectorTests extends AbstractVectorTest { } @Test(dataProvider = "floatTestOpMaskProvider") - static void IS_NANMaskedFloatMaxVectorTestsSmokeTest(IntFunction fa, + static void IS_NANMaskedFloatMaxVectorTests(IntFunction fa, IntFunction fm) { float[] a = fa.apply(SPECIES.length()); boolean[] mask = fm.apply(SPECIES.length()); VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); - for (int i = 0; i < a.length; i += SPECIES.length()) { - FloatVector av = FloatVector.fromArray(SPECIES, a, i); - VectorMask mv = av.test(VectorOperators.IS_NAN, vmask); + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + FloatVector av = FloatVector.fromArray(SPECIES, a, i); + VectorMask mv = av.test(VectorOperators.IS_NAN, vmask); - // Check results as part of computation. - for (int j = 0; j < SPECIES.length(); j++) { - Assert.assertEquals(mv.laneIsSet(j), vmask.laneIsSet(j) && testIS_NAN(a[i + j])); + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + Assert.assertEquals(mv.laneIsSet(j), vmask.laneIsSet(j) && testIS_NAN(a[i + j])); + } } } } @@ -2749,19 +2757,21 @@ public class FloatMaxVectorTests extends AbstractVectorTest { } @Test(dataProvider = "floatTestOpMaskProvider") - static void IS_INFINITEMaskedFloatMaxVectorTestsSmokeTest(IntFunction fa, + static void IS_INFINITEMaskedFloatMaxVectorTests(IntFunction fa, IntFunction fm) { float[] a = fa.apply(SPECIES.length()); boolean[] mask = fm.apply(SPECIES.length()); VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); - for (int i = 0; i < a.length; i += SPECIES.length()) { - FloatVector av = FloatVector.fromArray(SPECIES, a, i); - VectorMask mv = av.test(VectorOperators.IS_INFINITE, vmask); + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + FloatVector av = FloatVector.fromArray(SPECIES, a, i); + VectorMask mv = av.test(VectorOperators.IS_INFINITE, vmask); - // Check results as part of computation. - for (int j = 0; j < SPECIES.length(); j++) { - Assert.assertEquals(mv.laneIsSet(j), vmask.laneIsSet(j) && testIS_INFINITE(a[i + j])); + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + Assert.assertEquals(mv.laneIsSet(j), vmask.laneIsSet(j) && testIS_INFINITE(a[i + j])); + } } } } diff --git a/test/jdk/jdk/incubator/vector/Int128VectorTests.java b/test/jdk/jdk/incubator/vector/Int128VectorTests.java index 99bc02b823975965fe9c9dbbaad9c4edc5c124a3..4de0a1b30446553b4d5c9499e11b45d500dfb3a8 100644 --- a/test/jdk/jdk/incubator/vector/Int128VectorTests.java +++ b/test/jdk/jdk/incubator/vector/Int128VectorTests.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 @@ -3529,19 +3529,21 @@ public class Int128VectorTests extends AbstractVectorTest { } @Test(dataProvider = "intTestOpMaskProvider") - static void IS_DEFAULTMaskedInt128VectorTestsSmokeTest(IntFunction fa, + static void IS_DEFAULTMaskedInt128VectorTests(IntFunction fa, IntFunction fm) { int[] a = fa.apply(SPECIES.length()); boolean[] mask = fm.apply(SPECIES.length()); VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); - for (int i = 0; i < a.length; i += SPECIES.length()) { - IntVector av = IntVector.fromArray(SPECIES, a, i); - VectorMask mv = av.test(VectorOperators.IS_DEFAULT, vmask); + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + IntVector av = IntVector.fromArray(SPECIES, a, i); + VectorMask mv = av.test(VectorOperators.IS_DEFAULT, vmask); - // Check results as part of computation. - for (int j = 0; j < SPECIES.length(); j++) { - Assert.assertEquals(mv.laneIsSet(j), vmask.laneIsSet(j) && testIS_DEFAULT(a[i + j])); + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + Assert.assertEquals(mv.laneIsSet(j), vmask.laneIsSet(j) && testIS_DEFAULT(a[i + j])); + } } } } @@ -3567,19 +3569,21 @@ public class Int128VectorTests extends AbstractVectorTest { } @Test(dataProvider = "intTestOpMaskProvider") - static void IS_NEGATIVEMaskedInt128VectorTestsSmokeTest(IntFunction fa, + static void IS_NEGATIVEMaskedInt128VectorTests(IntFunction fa, IntFunction fm) { int[] a = fa.apply(SPECIES.length()); boolean[] mask = fm.apply(SPECIES.length()); VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); - for (int i = 0; i < a.length; i += SPECIES.length()) { - IntVector av = IntVector.fromArray(SPECIES, a, i); - VectorMask mv = av.test(VectorOperators.IS_NEGATIVE, vmask); + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + IntVector av = IntVector.fromArray(SPECIES, a, i); + VectorMask mv = av.test(VectorOperators.IS_NEGATIVE, vmask); - // Check results as part of computation. - for (int j = 0; j < SPECIES.length(); j++) { - Assert.assertEquals(mv.laneIsSet(j), vmask.laneIsSet(j) && testIS_NEGATIVE(a[i + j])); + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + Assert.assertEquals(mv.laneIsSet(j), vmask.laneIsSet(j) && testIS_NEGATIVE(a[i + j])); + } } } } diff --git a/test/jdk/jdk/incubator/vector/Int256VectorTests.java b/test/jdk/jdk/incubator/vector/Int256VectorTests.java index e4b3f491e3151554c90c47beeb93f1a6f86a16ba..597d5c6fdbbb28f707d54281995f29e36db4b70c 100644 --- a/test/jdk/jdk/incubator/vector/Int256VectorTests.java +++ b/test/jdk/jdk/incubator/vector/Int256VectorTests.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 @@ -3529,19 +3529,21 @@ public class Int256VectorTests extends AbstractVectorTest { } @Test(dataProvider = "intTestOpMaskProvider") - static void IS_DEFAULTMaskedInt256VectorTestsSmokeTest(IntFunction fa, + static void IS_DEFAULTMaskedInt256VectorTests(IntFunction fa, IntFunction fm) { int[] a = fa.apply(SPECIES.length()); boolean[] mask = fm.apply(SPECIES.length()); VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); - for (int i = 0; i < a.length; i += SPECIES.length()) { - IntVector av = IntVector.fromArray(SPECIES, a, i); - VectorMask mv = av.test(VectorOperators.IS_DEFAULT, vmask); + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + IntVector av = IntVector.fromArray(SPECIES, a, i); + VectorMask mv = av.test(VectorOperators.IS_DEFAULT, vmask); - // Check results as part of computation. - for (int j = 0; j < SPECIES.length(); j++) { - Assert.assertEquals(mv.laneIsSet(j), vmask.laneIsSet(j) && testIS_DEFAULT(a[i + j])); + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + Assert.assertEquals(mv.laneIsSet(j), vmask.laneIsSet(j) && testIS_DEFAULT(a[i + j])); + } } } } @@ -3567,19 +3569,21 @@ public class Int256VectorTests extends AbstractVectorTest { } @Test(dataProvider = "intTestOpMaskProvider") - static void IS_NEGATIVEMaskedInt256VectorTestsSmokeTest(IntFunction fa, + static void IS_NEGATIVEMaskedInt256VectorTests(IntFunction fa, IntFunction fm) { int[] a = fa.apply(SPECIES.length()); boolean[] mask = fm.apply(SPECIES.length()); VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); - for (int i = 0; i < a.length; i += SPECIES.length()) { - IntVector av = IntVector.fromArray(SPECIES, a, i); - VectorMask mv = av.test(VectorOperators.IS_NEGATIVE, vmask); + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + IntVector av = IntVector.fromArray(SPECIES, a, i); + VectorMask mv = av.test(VectorOperators.IS_NEGATIVE, vmask); - // Check results as part of computation. - for (int j = 0; j < SPECIES.length(); j++) { - Assert.assertEquals(mv.laneIsSet(j), vmask.laneIsSet(j) && testIS_NEGATIVE(a[i + j])); + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + Assert.assertEquals(mv.laneIsSet(j), vmask.laneIsSet(j) && testIS_NEGATIVE(a[i + j])); + } } } } diff --git a/test/jdk/jdk/incubator/vector/Int512VectorTests.java b/test/jdk/jdk/incubator/vector/Int512VectorTests.java index 503d24ab05c51d0deeae6c9ef645a2d38de950eb..075450c6adb06b35d70c8e4252802811347d6ca8 100644 --- a/test/jdk/jdk/incubator/vector/Int512VectorTests.java +++ b/test/jdk/jdk/incubator/vector/Int512VectorTests.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 @@ -3529,19 +3529,21 @@ public class Int512VectorTests extends AbstractVectorTest { } @Test(dataProvider = "intTestOpMaskProvider") - static void IS_DEFAULTMaskedInt512VectorTestsSmokeTest(IntFunction fa, + static void IS_DEFAULTMaskedInt512VectorTests(IntFunction fa, IntFunction fm) { int[] a = fa.apply(SPECIES.length()); boolean[] mask = fm.apply(SPECIES.length()); VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); - for (int i = 0; i < a.length; i += SPECIES.length()) { - IntVector av = IntVector.fromArray(SPECIES, a, i); - VectorMask mv = av.test(VectorOperators.IS_DEFAULT, vmask); + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + IntVector av = IntVector.fromArray(SPECIES, a, i); + VectorMask mv = av.test(VectorOperators.IS_DEFAULT, vmask); - // Check results as part of computation. - for (int j = 0; j < SPECIES.length(); j++) { - Assert.assertEquals(mv.laneIsSet(j), vmask.laneIsSet(j) && testIS_DEFAULT(a[i + j])); + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + Assert.assertEquals(mv.laneIsSet(j), vmask.laneIsSet(j) && testIS_DEFAULT(a[i + j])); + } } } } @@ -3567,19 +3569,21 @@ public class Int512VectorTests extends AbstractVectorTest { } @Test(dataProvider = "intTestOpMaskProvider") - static void IS_NEGATIVEMaskedInt512VectorTestsSmokeTest(IntFunction fa, + static void IS_NEGATIVEMaskedInt512VectorTests(IntFunction fa, IntFunction fm) { int[] a = fa.apply(SPECIES.length()); boolean[] mask = fm.apply(SPECIES.length()); VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); - for (int i = 0; i < a.length; i += SPECIES.length()) { - IntVector av = IntVector.fromArray(SPECIES, a, i); - VectorMask mv = av.test(VectorOperators.IS_NEGATIVE, vmask); + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + IntVector av = IntVector.fromArray(SPECIES, a, i); + VectorMask mv = av.test(VectorOperators.IS_NEGATIVE, vmask); - // Check results as part of computation. - for (int j = 0; j < SPECIES.length(); j++) { - Assert.assertEquals(mv.laneIsSet(j), vmask.laneIsSet(j) && testIS_NEGATIVE(a[i + j])); + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + Assert.assertEquals(mv.laneIsSet(j), vmask.laneIsSet(j) && testIS_NEGATIVE(a[i + j])); + } } } } diff --git a/test/jdk/jdk/incubator/vector/Int64VectorTests.java b/test/jdk/jdk/incubator/vector/Int64VectorTests.java index 2bebc06d0e2654cb7842c79b6a23a83315c55e35..0d2346215d142e5eb2d734af17b8891d4ca8e0d4 100644 --- a/test/jdk/jdk/incubator/vector/Int64VectorTests.java +++ b/test/jdk/jdk/incubator/vector/Int64VectorTests.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 @@ -3529,19 +3529,21 @@ public class Int64VectorTests extends AbstractVectorTest { } @Test(dataProvider = "intTestOpMaskProvider") - static void IS_DEFAULTMaskedInt64VectorTestsSmokeTest(IntFunction fa, + static void IS_DEFAULTMaskedInt64VectorTests(IntFunction fa, IntFunction fm) { int[] a = fa.apply(SPECIES.length()); boolean[] mask = fm.apply(SPECIES.length()); VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); - for (int i = 0; i < a.length; i += SPECIES.length()) { - IntVector av = IntVector.fromArray(SPECIES, a, i); - VectorMask mv = av.test(VectorOperators.IS_DEFAULT, vmask); + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + IntVector av = IntVector.fromArray(SPECIES, a, i); + VectorMask mv = av.test(VectorOperators.IS_DEFAULT, vmask); - // Check results as part of computation. - for (int j = 0; j < SPECIES.length(); j++) { - Assert.assertEquals(mv.laneIsSet(j), vmask.laneIsSet(j) && testIS_DEFAULT(a[i + j])); + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + Assert.assertEquals(mv.laneIsSet(j), vmask.laneIsSet(j) && testIS_DEFAULT(a[i + j])); + } } } } @@ -3567,19 +3569,21 @@ public class Int64VectorTests extends AbstractVectorTest { } @Test(dataProvider = "intTestOpMaskProvider") - static void IS_NEGATIVEMaskedInt64VectorTestsSmokeTest(IntFunction fa, + static void IS_NEGATIVEMaskedInt64VectorTests(IntFunction fa, IntFunction fm) { int[] a = fa.apply(SPECIES.length()); boolean[] mask = fm.apply(SPECIES.length()); VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); - for (int i = 0; i < a.length; i += SPECIES.length()) { - IntVector av = IntVector.fromArray(SPECIES, a, i); - VectorMask mv = av.test(VectorOperators.IS_NEGATIVE, vmask); + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + IntVector av = IntVector.fromArray(SPECIES, a, i); + VectorMask mv = av.test(VectorOperators.IS_NEGATIVE, vmask); - // Check results as part of computation. - for (int j = 0; j < SPECIES.length(); j++) { - Assert.assertEquals(mv.laneIsSet(j), vmask.laneIsSet(j) && testIS_NEGATIVE(a[i + j])); + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + Assert.assertEquals(mv.laneIsSet(j), vmask.laneIsSet(j) && testIS_NEGATIVE(a[i + j])); + } } } } diff --git a/test/jdk/jdk/incubator/vector/IntMaxVectorTests.java b/test/jdk/jdk/incubator/vector/IntMaxVectorTests.java index faf232e29853296d9dbd7438e6a7b9e80e6bb7f2..eb735c101e77368fd900a829d43d7f7e6f6ae13e 100644 --- a/test/jdk/jdk/incubator/vector/IntMaxVectorTests.java +++ b/test/jdk/jdk/incubator/vector/IntMaxVectorTests.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 @@ -3534,19 +3534,21 @@ public class IntMaxVectorTests extends AbstractVectorTest { } @Test(dataProvider = "intTestOpMaskProvider") - static void IS_DEFAULTMaskedIntMaxVectorTestsSmokeTest(IntFunction fa, + static void IS_DEFAULTMaskedIntMaxVectorTests(IntFunction fa, IntFunction fm) { int[] a = fa.apply(SPECIES.length()); boolean[] mask = fm.apply(SPECIES.length()); VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); - for (int i = 0; i < a.length; i += SPECIES.length()) { - IntVector av = IntVector.fromArray(SPECIES, a, i); - VectorMask mv = av.test(VectorOperators.IS_DEFAULT, vmask); + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + IntVector av = IntVector.fromArray(SPECIES, a, i); + VectorMask mv = av.test(VectorOperators.IS_DEFAULT, vmask); - // Check results as part of computation. - for (int j = 0; j < SPECIES.length(); j++) { - Assert.assertEquals(mv.laneIsSet(j), vmask.laneIsSet(j) && testIS_DEFAULT(a[i + j])); + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + Assert.assertEquals(mv.laneIsSet(j), vmask.laneIsSet(j) && testIS_DEFAULT(a[i + j])); + } } } } @@ -3572,19 +3574,21 @@ public class IntMaxVectorTests extends AbstractVectorTest { } @Test(dataProvider = "intTestOpMaskProvider") - static void IS_NEGATIVEMaskedIntMaxVectorTestsSmokeTest(IntFunction fa, + static void IS_NEGATIVEMaskedIntMaxVectorTests(IntFunction fa, IntFunction fm) { int[] a = fa.apply(SPECIES.length()); boolean[] mask = fm.apply(SPECIES.length()); VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); - for (int i = 0; i < a.length; i += SPECIES.length()) { - IntVector av = IntVector.fromArray(SPECIES, a, i); - VectorMask mv = av.test(VectorOperators.IS_NEGATIVE, vmask); + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + IntVector av = IntVector.fromArray(SPECIES, a, i); + VectorMask mv = av.test(VectorOperators.IS_NEGATIVE, vmask); - // Check results as part of computation. - for (int j = 0; j < SPECIES.length(); j++) { - Assert.assertEquals(mv.laneIsSet(j), vmask.laneIsSet(j) && testIS_NEGATIVE(a[i + j])); + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + Assert.assertEquals(mv.laneIsSet(j), vmask.laneIsSet(j) && testIS_NEGATIVE(a[i + j])); + } } } } diff --git a/test/jdk/jdk/incubator/vector/Long128VectorTests.java b/test/jdk/jdk/incubator/vector/Long128VectorTests.java index 74d251476b2fd2c611271d423bc298008ddda04f..da8c3fc802219bfbf4292c2904533eeb68cb9054 100644 --- a/test/jdk/jdk/incubator/vector/Long128VectorTests.java +++ b/test/jdk/jdk/incubator/vector/Long128VectorTests.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 @@ -3551,19 +3551,21 @@ public class Long128VectorTests extends AbstractVectorTest { } @Test(dataProvider = "longTestOpMaskProvider") - static void IS_DEFAULTMaskedLong128VectorTestsSmokeTest(IntFunction fa, + static void IS_DEFAULTMaskedLong128VectorTests(IntFunction fa, IntFunction fm) { long[] a = fa.apply(SPECIES.length()); boolean[] mask = fm.apply(SPECIES.length()); VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); - for (int i = 0; i < a.length; i += SPECIES.length()) { - LongVector av = LongVector.fromArray(SPECIES, a, i); - VectorMask mv = av.test(VectorOperators.IS_DEFAULT, vmask); + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + LongVector av = LongVector.fromArray(SPECIES, a, i); + VectorMask mv = av.test(VectorOperators.IS_DEFAULT, vmask); - // Check results as part of computation. - for (int j = 0; j < SPECIES.length(); j++) { - Assert.assertEquals(mv.laneIsSet(j), vmask.laneIsSet(j) && testIS_DEFAULT(a[i + j])); + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + Assert.assertEquals(mv.laneIsSet(j), vmask.laneIsSet(j) && testIS_DEFAULT(a[i + j])); + } } } } @@ -3589,19 +3591,21 @@ public class Long128VectorTests extends AbstractVectorTest { } @Test(dataProvider = "longTestOpMaskProvider") - static void IS_NEGATIVEMaskedLong128VectorTestsSmokeTest(IntFunction fa, + static void IS_NEGATIVEMaskedLong128VectorTests(IntFunction fa, IntFunction fm) { long[] a = fa.apply(SPECIES.length()); boolean[] mask = fm.apply(SPECIES.length()); VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); - for (int i = 0; i < a.length; i += SPECIES.length()) { - LongVector av = LongVector.fromArray(SPECIES, a, i); - VectorMask mv = av.test(VectorOperators.IS_NEGATIVE, vmask); + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + LongVector av = LongVector.fromArray(SPECIES, a, i); + VectorMask mv = av.test(VectorOperators.IS_NEGATIVE, vmask); - // Check results as part of computation. - for (int j = 0; j < SPECIES.length(); j++) { - Assert.assertEquals(mv.laneIsSet(j), vmask.laneIsSet(j) && testIS_NEGATIVE(a[i + j])); + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + Assert.assertEquals(mv.laneIsSet(j), vmask.laneIsSet(j) && testIS_NEGATIVE(a[i + j])); + } } } } diff --git a/test/jdk/jdk/incubator/vector/Long256VectorTests.java b/test/jdk/jdk/incubator/vector/Long256VectorTests.java index 4d2acbddd866f253037d4f83664139ede64d6a48..6e291fc3c100ba8e85df7e26b072afd9b438696a 100644 --- a/test/jdk/jdk/incubator/vector/Long256VectorTests.java +++ b/test/jdk/jdk/incubator/vector/Long256VectorTests.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 @@ -3551,19 +3551,21 @@ public class Long256VectorTests extends AbstractVectorTest { } @Test(dataProvider = "longTestOpMaskProvider") - static void IS_DEFAULTMaskedLong256VectorTestsSmokeTest(IntFunction fa, + static void IS_DEFAULTMaskedLong256VectorTests(IntFunction fa, IntFunction fm) { long[] a = fa.apply(SPECIES.length()); boolean[] mask = fm.apply(SPECIES.length()); VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); - for (int i = 0; i < a.length; i += SPECIES.length()) { - LongVector av = LongVector.fromArray(SPECIES, a, i); - VectorMask mv = av.test(VectorOperators.IS_DEFAULT, vmask); + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + LongVector av = LongVector.fromArray(SPECIES, a, i); + VectorMask mv = av.test(VectorOperators.IS_DEFAULT, vmask); - // Check results as part of computation. - for (int j = 0; j < SPECIES.length(); j++) { - Assert.assertEquals(mv.laneIsSet(j), vmask.laneIsSet(j) && testIS_DEFAULT(a[i + j])); + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + Assert.assertEquals(mv.laneIsSet(j), vmask.laneIsSet(j) && testIS_DEFAULT(a[i + j])); + } } } } @@ -3589,19 +3591,21 @@ public class Long256VectorTests extends AbstractVectorTest { } @Test(dataProvider = "longTestOpMaskProvider") - static void IS_NEGATIVEMaskedLong256VectorTestsSmokeTest(IntFunction fa, + static void IS_NEGATIVEMaskedLong256VectorTests(IntFunction fa, IntFunction fm) { long[] a = fa.apply(SPECIES.length()); boolean[] mask = fm.apply(SPECIES.length()); VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); - for (int i = 0; i < a.length; i += SPECIES.length()) { - LongVector av = LongVector.fromArray(SPECIES, a, i); - VectorMask mv = av.test(VectorOperators.IS_NEGATIVE, vmask); + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + LongVector av = LongVector.fromArray(SPECIES, a, i); + VectorMask mv = av.test(VectorOperators.IS_NEGATIVE, vmask); - // Check results as part of computation. - for (int j = 0; j < SPECIES.length(); j++) { - Assert.assertEquals(mv.laneIsSet(j), vmask.laneIsSet(j) && testIS_NEGATIVE(a[i + j])); + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + Assert.assertEquals(mv.laneIsSet(j), vmask.laneIsSet(j) && testIS_NEGATIVE(a[i + j])); + } } } } diff --git a/test/jdk/jdk/incubator/vector/Long512VectorTests.java b/test/jdk/jdk/incubator/vector/Long512VectorTests.java index 9bb6f568fca3efb05c70db6b8ac1edba1785020b..8b0e64d5ae4fa8789076bd40aacf6691563e952f 100644 --- a/test/jdk/jdk/incubator/vector/Long512VectorTests.java +++ b/test/jdk/jdk/incubator/vector/Long512VectorTests.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 @@ -3551,19 +3551,21 @@ public class Long512VectorTests extends AbstractVectorTest { } @Test(dataProvider = "longTestOpMaskProvider") - static void IS_DEFAULTMaskedLong512VectorTestsSmokeTest(IntFunction fa, + static void IS_DEFAULTMaskedLong512VectorTests(IntFunction fa, IntFunction fm) { long[] a = fa.apply(SPECIES.length()); boolean[] mask = fm.apply(SPECIES.length()); VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); - for (int i = 0; i < a.length; i += SPECIES.length()) { - LongVector av = LongVector.fromArray(SPECIES, a, i); - VectorMask mv = av.test(VectorOperators.IS_DEFAULT, vmask); + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + LongVector av = LongVector.fromArray(SPECIES, a, i); + VectorMask mv = av.test(VectorOperators.IS_DEFAULT, vmask); - // Check results as part of computation. - for (int j = 0; j < SPECIES.length(); j++) { - Assert.assertEquals(mv.laneIsSet(j), vmask.laneIsSet(j) && testIS_DEFAULT(a[i + j])); + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + Assert.assertEquals(mv.laneIsSet(j), vmask.laneIsSet(j) && testIS_DEFAULT(a[i + j])); + } } } } @@ -3589,19 +3591,21 @@ public class Long512VectorTests extends AbstractVectorTest { } @Test(dataProvider = "longTestOpMaskProvider") - static void IS_NEGATIVEMaskedLong512VectorTestsSmokeTest(IntFunction fa, + static void IS_NEGATIVEMaskedLong512VectorTests(IntFunction fa, IntFunction fm) { long[] a = fa.apply(SPECIES.length()); boolean[] mask = fm.apply(SPECIES.length()); VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); - for (int i = 0; i < a.length; i += SPECIES.length()) { - LongVector av = LongVector.fromArray(SPECIES, a, i); - VectorMask mv = av.test(VectorOperators.IS_NEGATIVE, vmask); + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + LongVector av = LongVector.fromArray(SPECIES, a, i); + VectorMask mv = av.test(VectorOperators.IS_NEGATIVE, vmask); - // Check results as part of computation. - for (int j = 0; j < SPECIES.length(); j++) { - Assert.assertEquals(mv.laneIsSet(j), vmask.laneIsSet(j) && testIS_NEGATIVE(a[i + j])); + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + Assert.assertEquals(mv.laneIsSet(j), vmask.laneIsSet(j) && testIS_NEGATIVE(a[i + j])); + } } } } diff --git a/test/jdk/jdk/incubator/vector/Long64VectorTests.java b/test/jdk/jdk/incubator/vector/Long64VectorTests.java index 50976531dac793d16ab17a362d381524824eb701..f3134e72b21ededb385908052774779a470cb05c 100644 --- a/test/jdk/jdk/incubator/vector/Long64VectorTests.java +++ b/test/jdk/jdk/incubator/vector/Long64VectorTests.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 @@ -3551,19 +3551,21 @@ public class Long64VectorTests extends AbstractVectorTest { } @Test(dataProvider = "longTestOpMaskProvider") - static void IS_DEFAULTMaskedLong64VectorTestsSmokeTest(IntFunction fa, + static void IS_DEFAULTMaskedLong64VectorTests(IntFunction fa, IntFunction fm) { long[] a = fa.apply(SPECIES.length()); boolean[] mask = fm.apply(SPECIES.length()); VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); - for (int i = 0; i < a.length; i += SPECIES.length()) { - LongVector av = LongVector.fromArray(SPECIES, a, i); - VectorMask mv = av.test(VectorOperators.IS_DEFAULT, vmask); + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + LongVector av = LongVector.fromArray(SPECIES, a, i); + VectorMask mv = av.test(VectorOperators.IS_DEFAULT, vmask); - // Check results as part of computation. - for (int j = 0; j < SPECIES.length(); j++) { - Assert.assertEquals(mv.laneIsSet(j), vmask.laneIsSet(j) && testIS_DEFAULT(a[i + j])); + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + Assert.assertEquals(mv.laneIsSet(j), vmask.laneIsSet(j) && testIS_DEFAULT(a[i + j])); + } } } } @@ -3589,19 +3591,21 @@ public class Long64VectorTests extends AbstractVectorTest { } @Test(dataProvider = "longTestOpMaskProvider") - static void IS_NEGATIVEMaskedLong64VectorTestsSmokeTest(IntFunction fa, + static void IS_NEGATIVEMaskedLong64VectorTests(IntFunction fa, IntFunction fm) { long[] a = fa.apply(SPECIES.length()); boolean[] mask = fm.apply(SPECIES.length()); VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); - for (int i = 0; i < a.length; i += SPECIES.length()) { - LongVector av = LongVector.fromArray(SPECIES, a, i); - VectorMask mv = av.test(VectorOperators.IS_NEGATIVE, vmask); + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + LongVector av = LongVector.fromArray(SPECIES, a, i); + VectorMask mv = av.test(VectorOperators.IS_NEGATIVE, vmask); - // Check results as part of computation. - for (int j = 0; j < SPECIES.length(); j++) { - Assert.assertEquals(mv.laneIsSet(j), vmask.laneIsSet(j) && testIS_NEGATIVE(a[i + j])); + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + Assert.assertEquals(mv.laneIsSet(j), vmask.laneIsSet(j) && testIS_NEGATIVE(a[i + j])); + } } } } diff --git a/test/jdk/jdk/incubator/vector/LongMaxVectorTests.java b/test/jdk/jdk/incubator/vector/LongMaxVectorTests.java index eb16136a0d667d21986f14b7a224e76ebea31e0c..749ec641d3d59d80e6f95fece7057e6424dc6349 100644 --- a/test/jdk/jdk/incubator/vector/LongMaxVectorTests.java +++ b/test/jdk/jdk/incubator/vector/LongMaxVectorTests.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 @@ -3556,19 +3556,21 @@ public class LongMaxVectorTests extends AbstractVectorTest { } @Test(dataProvider = "longTestOpMaskProvider") - static void IS_DEFAULTMaskedLongMaxVectorTestsSmokeTest(IntFunction fa, + static void IS_DEFAULTMaskedLongMaxVectorTests(IntFunction fa, IntFunction fm) { long[] a = fa.apply(SPECIES.length()); boolean[] mask = fm.apply(SPECIES.length()); VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); - for (int i = 0; i < a.length; i += SPECIES.length()) { - LongVector av = LongVector.fromArray(SPECIES, a, i); - VectorMask mv = av.test(VectorOperators.IS_DEFAULT, vmask); + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + LongVector av = LongVector.fromArray(SPECIES, a, i); + VectorMask mv = av.test(VectorOperators.IS_DEFAULT, vmask); - // Check results as part of computation. - for (int j = 0; j < SPECIES.length(); j++) { - Assert.assertEquals(mv.laneIsSet(j), vmask.laneIsSet(j) && testIS_DEFAULT(a[i + j])); + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + Assert.assertEquals(mv.laneIsSet(j), vmask.laneIsSet(j) && testIS_DEFAULT(a[i + j])); + } } } } @@ -3594,19 +3596,21 @@ public class LongMaxVectorTests extends AbstractVectorTest { } @Test(dataProvider = "longTestOpMaskProvider") - static void IS_NEGATIVEMaskedLongMaxVectorTestsSmokeTest(IntFunction fa, + static void IS_NEGATIVEMaskedLongMaxVectorTests(IntFunction fa, IntFunction fm) { long[] a = fa.apply(SPECIES.length()); boolean[] mask = fm.apply(SPECIES.length()); VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); - for (int i = 0; i < a.length; i += SPECIES.length()) { - LongVector av = LongVector.fromArray(SPECIES, a, i); - VectorMask mv = av.test(VectorOperators.IS_NEGATIVE, vmask); + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + LongVector av = LongVector.fromArray(SPECIES, a, i); + VectorMask mv = av.test(VectorOperators.IS_NEGATIVE, vmask); - // Check results as part of computation. - for (int j = 0; j < SPECIES.length(); j++) { - Assert.assertEquals(mv.laneIsSet(j), vmask.laneIsSet(j) && testIS_NEGATIVE(a[i + j])); + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + Assert.assertEquals(mv.laneIsSet(j), vmask.laneIsSet(j) && testIS_NEGATIVE(a[i + j])); + } } } } diff --git a/test/jdk/jdk/incubator/vector/Short128VectorTests.java b/test/jdk/jdk/incubator/vector/Short128VectorTests.java index 2a060c354cd19c8cface94e373ecbd676326ccfe..e933c0eaac539c734d5f48d4f42368684b12c8db 100644 --- a/test/jdk/jdk/incubator/vector/Short128VectorTests.java +++ b/test/jdk/jdk/incubator/vector/Short128VectorTests.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 @@ -3554,19 +3554,21 @@ public class Short128VectorTests extends AbstractVectorTest { } @Test(dataProvider = "shortTestOpMaskProvider") - static void IS_DEFAULTMaskedShort128VectorTestsSmokeTest(IntFunction fa, + static void IS_DEFAULTMaskedShort128VectorTests(IntFunction fa, IntFunction fm) { short[] a = fa.apply(SPECIES.length()); boolean[] mask = fm.apply(SPECIES.length()); VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); - for (int i = 0; i < a.length; i += SPECIES.length()) { - ShortVector av = ShortVector.fromArray(SPECIES, a, i); - VectorMask mv = av.test(VectorOperators.IS_DEFAULT, vmask); + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + ShortVector av = ShortVector.fromArray(SPECIES, a, i); + VectorMask mv = av.test(VectorOperators.IS_DEFAULT, vmask); - // Check results as part of computation. - for (int j = 0; j < SPECIES.length(); j++) { - Assert.assertEquals(mv.laneIsSet(j), vmask.laneIsSet(j) && testIS_DEFAULT(a[i + j])); + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + Assert.assertEquals(mv.laneIsSet(j), vmask.laneIsSet(j) && testIS_DEFAULT(a[i + j])); + } } } } @@ -3592,19 +3594,21 @@ public class Short128VectorTests extends AbstractVectorTest { } @Test(dataProvider = "shortTestOpMaskProvider") - static void IS_NEGATIVEMaskedShort128VectorTestsSmokeTest(IntFunction fa, + static void IS_NEGATIVEMaskedShort128VectorTests(IntFunction fa, IntFunction fm) { short[] a = fa.apply(SPECIES.length()); boolean[] mask = fm.apply(SPECIES.length()); VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); - for (int i = 0; i < a.length; i += SPECIES.length()) { - ShortVector av = ShortVector.fromArray(SPECIES, a, i); - VectorMask mv = av.test(VectorOperators.IS_NEGATIVE, vmask); + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + ShortVector av = ShortVector.fromArray(SPECIES, a, i); + VectorMask mv = av.test(VectorOperators.IS_NEGATIVE, vmask); - // Check results as part of computation. - for (int j = 0; j < SPECIES.length(); j++) { - Assert.assertEquals(mv.laneIsSet(j), vmask.laneIsSet(j) && testIS_NEGATIVE(a[i + j])); + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + Assert.assertEquals(mv.laneIsSet(j), vmask.laneIsSet(j) && testIS_NEGATIVE(a[i + j])); + } } } } diff --git a/test/jdk/jdk/incubator/vector/Short256VectorTests.java b/test/jdk/jdk/incubator/vector/Short256VectorTests.java index 46626d63aafb2611667cd3771ebc9cc5f9a13059..75f7129e14bbfaf4fe9b3ad1c6920c27a5c07478 100644 --- a/test/jdk/jdk/incubator/vector/Short256VectorTests.java +++ b/test/jdk/jdk/incubator/vector/Short256VectorTests.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 @@ -3554,19 +3554,21 @@ public class Short256VectorTests extends AbstractVectorTest { } @Test(dataProvider = "shortTestOpMaskProvider") - static void IS_DEFAULTMaskedShort256VectorTestsSmokeTest(IntFunction fa, + static void IS_DEFAULTMaskedShort256VectorTests(IntFunction fa, IntFunction fm) { short[] a = fa.apply(SPECIES.length()); boolean[] mask = fm.apply(SPECIES.length()); VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); - for (int i = 0; i < a.length; i += SPECIES.length()) { - ShortVector av = ShortVector.fromArray(SPECIES, a, i); - VectorMask mv = av.test(VectorOperators.IS_DEFAULT, vmask); + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + ShortVector av = ShortVector.fromArray(SPECIES, a, i); + VectorMask mv = av.test(VectorOperators.IS_DEFAULT, vmask); - // Check results as part of computation. - for (int j = 0; j < SPECIES.length(); j++) { - Assert.assertEquals(mv.laneIsSet(j), vmask.laneIsSet(j) && testIS_DEFAULT(a[i + j])); + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + Assert.assertEquals(mv.laneIsSet(j), vmask.laneIsSet(j) && testIS_DEFAULT(a[i + j])); + } } } } @@ -3592,19 +3594,21 @@ public class Short256VectorTests extends AbstractVectorTest { } @Test(dataProvider = "shortTestOpMaskProvider") - static void IS_NEGATIVEMaskedShort256VectorTestsSmokeTest(IntFunction fa, + static void IS_NEGATIVEMaskedShort256VectorTests(IntFunction fa, IntFunction fm) { short[] a = fa.apply(SPECIES.length()); boolean[] mask = fm.apply(SPECIES.length()); VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); - for (int i = 0; i < a.length; i += SPECIES.length()) { - ShortVector av = ShortVector.fromArray(SPECIES, a, i); - VectorMask mv = av.test(VectorOperators.IS_NEGATIVE, vmask); + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + ShortVector av = ShortVector.fromArray(SPECIES, a, i); + VectorMask mv = av.test(VectorOperators.IS_NEGATIVE, vmask); - // Check results as part of computation. - for (int j = 0; j < SPECIES.length(); j++) { - Assert.assertEquals(mv.laneIsSet(j), vmask.laneIsSet(j) && testIS_NEGATIVE(a[i + j])); + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + Assert.assertEquals(mv.laneIsSet(j), vmask.laneIsSet(j) && testIS_NEGATIVE(a[i + j])); + } } } } diff --git a/test/jdk/jdk/incubator/vector/Short512VectorTests.java b/test/jdk/jdk/incubator/vector/Short512VectorTests.java index 2cff4a4802a03f98273d48cbcd5787a055fb526d..af7eea3b2c8dc40186a8d2a58e347a07eef8b466 100644 --- a/test/jdk/jdk/incubator/vector/Short512VectorTests.java +++ b/test/jdk/jdk/incubator/vector/Short512VectorTests.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 @@ -3554,19 +3554,21 @@ public class Short512VectorTests extends AbstractVectorTest { } @Test(dataProvider = "shortTestOpMaskProvider") - static void IS_DEFAULTMaskedShort512VectorTestsSmokeTest(IntFunction fa, + static void IS_DEFAULTMaskedShort512VectorTests(IntFunction fa, IntFunction fm) { short[] a = fa.apply(SPECIES.length()); boolean[] mask = fm.apply(SPECIES.length()); VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); - for (int i = 0; i < a.length; i += SPECIES.length()) { - ShortVector av = ShortVector.fromArray(SPECIES, a, i); - VectorMask mv = av.test(VectorOperators.IS_DEFAULT, vmask); + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + ShortVector av = ShortVector.fromArray(SPECIES, a, i); + VectorMask mv = av.test(VectorOperators.IS_DEFAULT, vmask); - // Check results as part of computation. - for (int j = 0; j < SPECIES.length(); j++) { - Assert.assertEquals(mv.laneIsSet(j), vmask.laneIsSet(j) && testIS_DEFAULT(a[i + j])); + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + Assert.assertEquals(mv.laneIsSet(j), vmask.laneIsSet(j) && testIS_DEFAULT(a[i + j])); + } } } } @@ -3592,19 +3594,21 @@ public class Short512VectorTests extends AbstractVectorTest { } @Test(dataProvider = "shortTestOpMaskProvider") - static void IS_NEGATIVEMaskedShort512VectorTestsSmokeTest(IntFunction fa, + static void IS_NEGATIVEMaskedShort512VectorTests(IntFunction fa, IntFunction fm) { short[] a = fa.apply(SPECIES.length()); boolean[] mask = fm.apply(SPECIES.length()); VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); - for (int i = 0; i < a.length; i += SPECIES.length()) { - ShortVector av = ShortVector.fromArray(SPECIES, a, i); - VectorMask mv = av.test(VectorOperators.IS_NEGATIVE, vmask); + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + ShortVector av = ShortVector.fromArray(SPECIES, a, i); + VectorMask mv = av.test(VectorOperators.IS_NEGATIVE, vmask); - // Check results as part of computation. - for (int j = 0; j < SPECIES.length(); j++) { - Assert.assertEquals(mv.laneIsSet(j), vmask.laneIsSet(j) && testIS_NEGATIVE(a[i + j])); + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + Assert.assertEquals(mv.laneIsSet(j), vmask.laneIsSet(j) && testIS_NEGATIVE(a[i + j])); + } } } } diff --git a/test/jdk/jdk/incubator/vector/Short64VectorTests.java b/test/jdk/jdk/incubator/vector/Short64VectorTests.java index 481081b75dae68b5fcb064941e5813ef4ad5e60d..100bc4e3243aa2a9874ff56534919d4b6d239b39 100644 --- a/test/jdk/jdk/incubator/vector/Short64VectorTests.java +++ b/test/jdk/jdk/incubator/vector/Short64VectorTests.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 @@ -3554,19 +3554,21 @@ public class Short64VectorTests extends AbstractVectorTest { } @Test(dataProvider = "shortTestOpMaskProvider") - static void IS_DEFAULTMaskedShort64VectorTestsSmokeTest(IntFunction fa, + static void IS_DEFAULTMaskedShort64VectorTests(IntFunction fa, IntFunction fm) { short[] a = fa.apply(SPECIES.length()); boolean[] mask = fm.apply(SPECIES.length()); VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); - for (int i = 0; i < a.length; i += SPECIES.length()) { - ShortVector av = ShortVector.fromArray(SPECIES, a, i); - VectorMask mv = av.test(VectorOperators.IS_DEFAULT, vmask); + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + ShortVector av = ShortVector.fromArray(SPECIES, a, i); + VectorMask mv = av.test(VectorOperators.IS_DEFAULT, vmask); - // Check results as part of computation. - for (int j = 0; j < SPECIES.length(); j++) { - Assert.assertEquals(mv.laneIsSet(j), vmask.laneIsSet(j) && testIS_DEFAULT(a[i + j])); + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + Assert.assertEquals(mv.laneIsSet(j), vmask.laneIsSet(j) && testIS_DEFAULT(a[i + j])); + } } } } @@ -3592,19 +3594,21 @@ public class Short64VectorTests extends AbstractVectorTest { } @Test(dataProvider = "shortTestOpMaskProvider") - static void IS_NEGATIVEMaskedShort64VectorTestsSmokeTest(IntFunction fa, + static void IS_NEGATIVEMaskedShort64VectorTests(IntFunction fa, IntFunction fm) { short[] a = fa.apply(SPECIES.length()); boolean[] mask = fm.apply(SPECIES.length()); VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); - for (int i = 0; i < a.length; i += SPECIES.length()) { - ShortVector av = ShortVector.fromArray(SPECIES, a, i); - VectorMask mv = av.test(VectorOperators.IS_NEGATIVE, vmask); + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + ShortVector av = ShortVector.fromArray(SPECIES, a, i); + VectorMask mv = av.test(VectorOperators.IS_NEGATIVE, vmask); - // Check results as part of computation. - for (int j = 0; j < SPECIES.length(); j++) { - Assert.assertEquals(mv.laneIsSet(j), vmask.laneIsSet(j) && testIS_NEGATIVE(a[i + j])); + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + Assert.assertEquals(mv.laneIsSet(j), vmask.laneIsSet(j) && testIS_NEGATIVE(a[i + j])); + } } } } diff --git a/test/jdk/jdk/incubator/vector/ShortMaxVectorTests.java b/test/jdk/jdk/incubator/vector/ShortMaxVectorTests.java index 00d99484a1309e45b878548dc38bdb635f5e701f..bd71da2ab8e568e0f7e3f61791b5b17fe911ee61 100644 --- a/test/jdk/jdk/incubator/vector/ShortMaxVectorTests.java +++ b/test/jdk/jdk/incubator/vector/ShortMaxVectorTests.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 @@ -3559,19 +3559,21 @@ public class ShortMaxVectorTests extends AbstractVectorTest { } @Test(dataProvider = "shortTestOpMaskProvider") - static void IS_DEFAULTMaskedShortMaxVectorTestsSmokeTest(IntFunction fa, + static void IS_DEFAULTMaskedShortMaxVectorTests(IntFunction fa, IntFunction fm) { short[] a = fa.apply(SPECIES.length()); boolean[] mask = fm.apply(SPECIES.length()); VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); - for (int i = 0; i < a.length; i += SPECIES.length()) { - ShortVector av = ShortVector.fromArray(SPECIES, a, i); - VectorMask mv = av.test(VectorOperators.IS_DEFAULT, vmask); + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + ShortVector av = ShortVector.fromArray(SPECIES, a, i); + VectorMask mv = av.test(VectorOperators.IS_DEFAULT, vmask); - // Check results as part of computation. - for (int j = 0; j < SPECIES.length(); j++) { - Assert.assertEquals(mv.laneIsSet(j), vmask.laneIsSet(j) && testIS_DEFAULT(a[i + j])); + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + Assert.assertEquals(mv.laneIsSet(j), vmask.laneIsSet(j) && testIS_DEFAULT(a[i + j])); + } } } } @@ -3597,19 +3599,21 @@ public class ShortMaxVectorTests extends AbstractVectorTest { } @Test(dataProvider = "shortTestOpMaskProvider") - static void IS_NEGATIVEMaskedShortMaxVectorTestsSmokeTest(IntFunction fa, + static void IS_NEGATIVEMaskedShortMaxVectorTests(IntFunction fa, IntFunction fm) { short[] a = fa.apply(SPECIES.length()); boolean[] mask = fm.apply(SPECIES.length()); VectorMask vmask = VectorMask.fromArray(SPECIES, mask, 0); - for (int i = 0; i < a.length; i += SPECIES.length()) { - ShortVector av = ShortVector.fromArray(SPECIES, a, i); - VectorMask mv = av.test(VectorOperators.IS_NEGATIVE, vmask); + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + ShortVector av = ShortVector.fromArray(SPECIES, a, i); + VectorMask mv = av.test(VectorOperators.IS_NEGATIVE, vmask); - // Check results as part of computation. - for (int j = 0; j < SPECIES.length(); j++) { - Assert.assertEquals(mv.laneIsSet(j), vmask.laneIsSet(j) && testIS_NEGATIVE(a[i + j])); + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + Assert.assertEquals(mv.laneIsSet(j), vmask.laneIsSet(j) && testIS_NEGATIVE(a[i + j])); + } } } } diff --git a/test/jdk/jdk/incubator/vector/VectorMaxConversionTests.java b/test/jdk/jdk/incubator/vector/VectorMaxConversionTests.java index bab60cc684a4cb34f0c31382da74988278d79a57..6b45043cc629701fa51b8d7f71daf3785e82655f 100644 --- a/test/jdk/jdk/incubator/vector/VectorMaxConversionTests.java +++ b/test/jdk/jdk/incubator/vector/VectorMaxConversionTests.java @@ -40,6 +40,18 @@ import java.util.List; * VectorMaxConversionTests */ +/* + * @test + * @bug 8281544 + * @summary Test that ZGC and vectorapi with KNL work together. + * @requires vm.gc.Z + * @modules jdk.incubator.vector + * @modules java.base/jdk.internal.vm.annotation + * @run testng/othervm -XX:-TieredCompilation --add-opens jdk.incubator.vector/jdk.incubator.vector=ALL-UNNAMED + * -XX:+UnlockDiagnosticVMOptions -XX:+UseKNLSetting -XX:+UseZGC -XX:+IgnoreUnrecognizedVMOptions + * VectorMaxConversionTests + */ + @Test public class VectorMaxConversionTests extends AbstractVectorConversionTest { diff --git a/test/jdk/jdk/incubator/vector/templates/Unit-Test.template b/test/jdk/jdk/incubator/vector/templates/Unit-Test.template index 03cb5a48733d6ec7181294acb738edc22bcc7163..c91be6191d24d78f2496c7afc7f6113919fee8c9 100644 --- a/test/jdk/jdk/incubator/vector/templates/Unit-Test.template +++ b/test/jdk/jdk/incubator/vector/templates/Unit-Test.template @@ -20,19 +20,21 @@ } @Test(dataProvider = "$type$TestOpMaskProvider") - static void [[TEST]]Masked$vectorteststype$SmokeTest(IntFunction<$type$[]> fa, + static void [[TEST]]Masked$vectorteststype$(IntFunction<$type$[]> fa, IntFunction fm) { $type$[] a = fa.apply(SPECIES.length()); boolean[] mask = fm.apply(SPECIES.length()); VectorMask<$Wideboxtype$> vmask = VectorMask.fromArray(SPECIES, mask, 0); - for (int i = 0; i < a.length; i += SPECIES.length()) { - $abstractvectortype$ av = $abstractvectortype$.fromArray(SPECIES, a, i); - VectorMask<$Wideboxtype$> mv = av.test(VectorOperators.[[TEST]], vmask); + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + $abstractvectortype$ av = $abstractvectortype$.fromArray(SPECIES, a, i); + VectorMask<$Wideboxtype$> mv = av.test(VectorOperators.[[TEST]], vmask); - // Check results as part of computation. - for (int j = 0; j < SPECIES.length(); j++) { - Assert.assertEquals(mv.laneIsSet(j), vmask.laneIsSet(j) && test[[TEST]](a[i + j])); + // Check results as part of computation. + for (int j = 0; j < SPECIES.length(); j++) { + Assert.assertEquals(mv.laneIsSet(j), vmask.laneIsSet(j) && test[[TEST]](a[i + j])); + } } } } diff --git a/test/jdk/jdk/incubator/vector/templates/Unit-header.template b/test/jdk/jdk/incubator/vector/templates/Unit-header.template index 239596bf433364cae84bf7eeab27e06e4ec8e636..e010bb7268b6aed8d696bce772fb96a033af7ba8 100644 --- a/test/jdk/jdk/incubator/vector/templates/Unit-header.template +++ b/test/jdk/jdk/incubator/vector/templates/Unit-header.template @@ -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 diff --git a/test/jdk/jdk/internal/loader/NativeLibraries/Main.java b/test/jdk/jdk/internal/loader/NativeLibraries/Main.java index 3693217dfd29eb9764d34bdb5c68a955e6ec9363..638047c33e0682227f396ee24b9e13a650004fda 100644 --- a/test/jdk/jdk/internal/loader/NativeLibraries/Main.java +++ b/test/jdk/jdk/internal/loader/NativeLibraries/Main.java @@ -54,10 +54,13 @@ public class Main { System.loadLibrary(NativeLibrariesTest.LIB_NAME); // expect NativeLibraries to succeed even the library has been loaded by System::loadLibrary - test.load(true); + test.loadTestLibrary(); // load zip library from JDK - test.load(System.mapLibraryName("zip")); + test.load(System.mapLibraryName("zip"), true /* succeed */); + + // load non-existent library + test.load(System.mapLibraryName("NotExist"), false /* fail to load */); } /* * move p/Test.class out from classpath to the scratch directory diff --git a/test/jdk/jdk/internal/loader/NativeLibraries/java.base/jdk/internal/loader/NativeLibrariesTest.java b/test/jdk/jdk/internal/loader/NativeLibraries/java.base/jdk/internal/loader/NativeLibrariesTest.java index dcb482cac7432d1d4df65e52e067e13bdcf0db81..a0560624929bea9190b8f61aaddd574cea9a67fe 100644 --- a/test/jdk/jdk/internal/loader/NativeLibraries/java.base/jdk/internal/loader/NativeLibrariesTest.java +++ b/test/jdk/jdk/internal/loader/NativeLibraries/java.base/jdk/internal/loader/NativeLibrariesTest.java @@ -61,7 +61,7 @@ public class NativeLibrariesTest implements Runnable { * Invoke by p.Test to load the same native library from different class loader */ public void run() { - load(true); // expect loading of native library succeed + loadTestLibrary(); // expect loading of native library succeed } static Path libraryPath() { @@ -101,18 +101,18 @@ public class NativeLibrariesTest implements Runnable { assertTrue(unloadedCount == 0, "Native library unloaded. Expected: JNI_OnUnload not invoked"); } - public void load(boolean succeed) { + public void loadTestLibrary() { NativeLibrary nl = nativeLibraries.load(libraryPath()); - if (succeed) { - assertTrue(nl != null, "fail to load library"); - } else { - assertTrue(nl == null, "load library should fail"); - } + assertTrue(nl != null, "fail to load " + libraryPath()); } - public void load(String pathname) { + public void load(String pathname, boolean succeed) { NativeLibrary nl = nativeLibraries.load(pathname); - assertTrue(nl != null, "fail to load zip library"); + if (succeed) { + assertTrue(nl != null, "fail to load " + pathname); + } else { + assertTrue(nl == null, "expect to return null for " + pathname); + } } /* diff --git a/test/jdk/jdk/internal/platform/docker/GetFreeSwapSpaceSize.java b/test/jdk/jdk/internal/platform/docker/GetFreeSwapSpaceSize.java index efb6a39e4790469747a29ad985b9fee55c93b08b..92b8cf282b784f1f9256c3b8774665a61d0c7100 100644 --- a/test/jdk/jdk/internal/platform/docker/GetFreeSwapSpaceSize.java +++ b/test/jdk/jdk/internal/platform/docker/GetFreeSwapSpaceSize.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2020 THL A29 Limited, a Tencent company. All rights reserved. + * Copyright (C) 2020, 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 @@ -24,16 +24,36 @@ import com.sun.management.OperatingSystemMXBean; import java.lang.management.ManagementFactory; +// Usage: +// GetFreeSwapSpaceSize public class GetFreeSwapSpaceSize { public static void main(String[] args) { - System.out.println("TestGetFreeSwapSpaceSize"); + if (args.length != 4) { + throw new RuntimeException("Unexpected arguments. Expected 4, got " + args.length); + } + String memoryAlloc = args[0]; + long expectedMemory = Long.parseLong(args[1]); + String memorySwapAlloc = args[2]; + long expectedSwap = Long.parseLong(args[3]); + System.out.println("TestGetFreeSwapSpaceSize (memory=" + memoryAlloc + ", memorySwap=" + memorySwapAlloc + ")"); + if (expectedSwap != 0) { + throw new RuntimeException("Precondition of test not met: Expected swap size of 0, got: " + expectedSwap); + } OperatingSystemMXBean osBean = (OperatingSystemMXBean) ManagementFactory.getOperatingSystemMXBean(); + long osBeanTotalSwap = osBean.getTotalSwapSpaceSize(); + // Premise of this test is to test on a system where --memory and --memory-swap are set to + // the same amount via the container engine (i.e. no swap). In that case the OSBean must + // not report negative values for free swap space. Assert this precondition. + if (osBeanTotalSwap != expectedSwap) { + throw new RuntimeException("OperatingSystemMXBean.getTotalSwapSpaceSize() reported " + osBeanTotalSwap + " expected " + expectedSwap); + } + System.out.println("TestGetFreeSwapSpaceSize precondition met, osBeanTotalSwap = " + expectedSwap + ". Running test... "); for (int i = 0; i < 100; i++) { long size = osBean.getFreeSwapSpaceSize(); if (size < 0) { - System.out.println("Error: getFreeSwapSpaceSize returns " + size); - System.exit(-1); + throw new RuntimeException("Test failed! getFreeSwapSpaceSize returns " + size); } } + System.out.println("TestGetFreeSwapSpaceSize PASSED." ); } } diff --git a/test/jdk/jdk/internal/platform/docker/TestGetFreeSwapSpaceSize.java b/test/jdk/jdk/internal/platform/docker/TestGetFreeSwapSpaceSize.java index 319c55ab518e2be5dcbd7213966b22dcd4e94497..92f3364da10b002025e3b68a7ed6503842c1f55a 100644 --- a/test/jdk/jdk/internal/platform/docker/TestGetFreeSwapSpaceSize.java +++ b/test/jdk/jdk/internal/platform/docker/TestGetFreeSwapSpaceSize.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2020 THL A29 Limited, a Tencent company. All rights reserved. + * Copyright (C) 2020, 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 @@ -36,7 +36,7 @@ import jdk.test.lib.containers.docker.DockerTestUtils; import jdk.test.lib.process.OutputAnalyzer; public class TestGetFreeSwapSpaceSize { - private static final String imageName = Common.imageName("memory"); + private static final String imageName = Common.imageName("osbeanSwapSpace"); public static void main(String[] args) throws Exception { if (!DockerTestUtils.canTestDocker()) { @@ -58,17 +58,18 @@ public class TestGetFreeSwapSpaceSize { } private static void testGetFreeSwapSpaceSize(String memoryAllocation, String expectedMemory, - String swapAllocation, String expectedSwap) throws Exception { + String memorySwapAllocation, String expectedSwap) throws Exception { Common.logNewTestCase("TestGetFreeSwapSpaceSize"); DockerRunOptions opts = Common.newOpts(imageName, "GetFreeSwapSpaceSize") + .addClassOptions(memoryAllocation, expectedMemory, memorySwapAllocation, expectedSwap) .addDockerOpts( "--memory", memoryAllocation, - "--memory-swap", swapAllocation + "--memory-swap", memorySwapAllocation ); OutputAnalyzer out = DockerTestUtils.dockerRunJava(opts); out.shouldHaveExitValue(0) - .shouldContain("TestGetFreeSwapSpaceSize"); + .shouldContain("TestGetFreeSwapSpaceSize PASSED."); } } diff --git a/test/jdk/jdk/jfr/api/consumer/TestRecordingFile.java b/test/jdk/jdk/jfr/api/consumer/TestRecordingFile.java index 923895447c733304eb1fbe349bd9cb30f38f18c1..a81262f9405c82cfadf2e32d73056c13ac2fd23f 100644 --- a/test/jdk/jdk/jfr/api/consumer/TestRecordingFile.java +++ b/test/jdk/jdk/jfr/api/consumer/TestRecordingFile.java @@ -194,11 +194,11 @@ public class TestRecordingFile { rotator.stop(); } r2.stop(); - r2.dump(twoEventTypes);; + r2.dump(twoEventTypes); } FlightRecorder.register(Event3.class); r1.stop(); - r1.dump(threeEventTypes);; + r1.dump(threeEventTypes); } try (RecordingFile f = new RecordingFile(twoEventTypes)) { List types = f.readEventTypes(); diff --git a/test/jdk/jdk/jfr/api/consumer/TestRecordingFileSanitization.java b/test/jdk/jdk/jfr/api/consumer/TestRecordingFileSanitization.java new file mode 100644 index 0000000000000000000000000000000000000000..75e01f82cd403b18d921ee6e151a05b3fe9aec55 --- /dev/null +++ b/test/jdk/jdk/jfr/api/consumer/TestRecordingFileSanitization.java @@ -0,0 +1,121 @@ +/* + * 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.api.consumer; + +import jdk.jfr.Recording; +import jdk.jfr.consumer.RecordingFile; +import jdk.jfr.Name; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; + +import jdk.jfr.Event; + +/** + * @test + * @summary Verifies that all traces of sensitive data is removed + * @key jfr + * @requires vm.hasJFR + * @library /test/lib + * @run main/othervm jdk.jfr.api.consumer.TestRecordingFileSanitization + */ +public class TestRecordingFileSanitization { + // Less than 16 characters, stored in event + private final static String SHORT_PASSWORD = "abcde123"; + // More than 16 characters, stored in constant pool + private final static String LONG_PASSWORD = "abcdefghijklmnopqrstuvxyz1234567890"; + + @Name("Sensitive") + public static class SensitiveEvent extends Event { + String shortPassword; + String longPassword; + } + + public static void main(String[] args) throws Throwable { + Path sensitive = Path.of("sensitive.jfr"); + Path sanitized = Path.of("sanitized.jfr"); + try (Recording r = new Recording()) { + r.start(); + SensitiveEvent e = new SensitiveEvent(); + e.shortPassword = SHORT_PASSWORD; + e.longPassword = LONG_PASSWORD; + e.commit(); + r.stop(); + r.dump(sensitive); + } + try (RecordingFile r = new RecordingFile(sensitive)) { + r.write(sanitized, e -> !e.getEventType().getName().equals("Sensitive")); + } + + expect(sensitive, SHORT_PASSWORD); + expect(sensitive, LONG_PASSWORD); + missing(sanitized, SHORT_PASSWORD); + missing(sanitized, LONG_PASSWORD); + } + + private static void expect(Path file, String text) throws IOException { + if (!find(file, text)) { + throw new AssertionError("Expected to find '" + text +"' in " + file); + } + System.out.println("OK, found '" + text + "' in " + file ); + } + + private static void missing(Path file, String text) throws IOException { + if (find(file, text)) { + throw new AssertionError("Didn't expect to find '" + text +"' in " + file); + } + System.out.println("OK, missing '" + text + "' in " + file); + } + + private static boolean find(Path file, String text) throws IOException { + byte[] textBytes = stringToBytes(text); + byte[] fileBytes = Files.readAllBytes(file); + for (int i = 0; i < fileBytes.length - textBytes.length; i++) { + if (find(fileBytes, i, textBytes)) { + return true; + } + } + return false; + } + + private static boolean find(byte[] haystack, int start, byte[] needle) { + for (int i = 0; i < needle.length; i++) { + if (haystack[start + i] != needle[i]) { + return false; + } + } + return true; + } + + private static byte[] stringToBytes(String text) { + byte[] bytes = new byte[text.length()]; + for (int i = 0; i < text.length(); i++) { + if (text.charAt(i) > 127) { + throw new Error("Test only allows characters that becomes one byte with LEB128"); + } + bytes[i] = (byte)(text.charAt(i)); + } + return bytes; + } +} diff --git a/test/jdk/jdk/jfr/api/consumer/TestRecordingFileWrite.java b/test/jdk/jdk/jfr/api/consumer/TestRecordingFileWrite.java new file mode 100644 index 0000000000000000000000000000000000000000..f4cf5a20805fd5f8b41dfb95720590cb9a9fea20 --- /dev/null +++ b/test/jdk/jdk/jfr/api/consumer/TestRecordingFileWrite.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. + */ + +package jdk.jfr.api.consumer; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.ArrayDeque; +import java.util.Queue; +import java.util.Random; + +import jdk.jfr.Configuration; +import jdk.jfr.Event; +import jdk.jfr.Recording; +import jdk.jfr.consumer.RecordingFile; + +/** + * @test + * @summary Tests RecordingFile::write(Path, Predicate) + * @key jfr + * @requires vm.hasJFR + * @library /test/lib + * @run main/othervm jdk.jfr.api.consumer.TestRecordingFileWrite + */ +public class TestRecordingFileWrite { + + static class ScrubEvent extends Event { + long id; + String message; + } + + public static void main(String... args) throws Exception { + Path scrubbed = Paths.get("scrubbed.jfr"); + Path original = Paths.get("original.jfr"); + + createRecording(original); + Queue ids = scrubRecording(original, scrubbed); + System.out.println("Original size: " + Files.size(original)); + System.out.println("Scrubbed size: " + Files.size(scrubbed)); + System.out.println("Scrubbed event count: " + ids.size()); + if (ids.size() < 50_000) { + throw new AssertionError("Expected at least 50 000 events to be included"); + } + verify(scrubbed, ids); + } + + private static void verify(Path scrubbed, Queue events) throws Exception { + try (RecordingFile rf = new RecordingFile(scrubbed)) { + while (rf.hasMoreEvents()) { + String event = rf.readEvent().toString(); + String expected = events.poll(); + if (!event.equals(expected)) { + System.out.println("Found:"); + System.out.println(event); + System.out.println("Expected:"); + System.out.println(expected); + throw new Exception("Found event that should not be there. See log"); + } + } + } + if (!events.isEmpty()) { + throw new AssertionError("Missing events " + events); + } + } + + private static Queue scrubRecording(Path original, Path scrubbed) throws IOException { + Queue events = new ArrayDeque<>(150_000); + Random random = new Random(); + try (RecordingFile rf = new RecordingFile(original)) { + rf.write(scrubbed, event -> { + boolean keep = random.nextInt(10) == 0; + if (event.getEventType().getName().equals("jdk.OldObjectSample")) { + System.out.println(event); + keep = true; + } + if (keep) { + events.add(event.toString()); + } + return keep; + }); + } + return events; + } + + private static void createRecording(Path file) throws Exception { + // Use profile configuration so more complex data structures + // are serialized + Configuration c = Configuration.getConfiguration("profile"); + try (Recording r = new Recording(c)) { + r.start(); + String s = "A"; + // Generate sufficient number of events to provoke + // chunk rotations + for (int i = 0; i < 1_000_000; i++) { + ScrubEvent event = new ScrubEvent(); + event.message = s.repeat(i % 30); + event.id = i; + event.commit(); + } + r.stop(); + r.dump(file); + } + } +} diff --git a/test/jdk/jdk/jfr/api/consumer/filestream/TestReuse.java b/test/jdk/jdk/jfr/api/consumer/filestream/TestReuse.java index 3d7d143f44cdcededb793a6ea7565575f3409205..3dbe26eea16f3933c2f3316baae5aec5a088408a 100644 --- a/test/jdk/jdk/jfr/api/consumer/filestream/TestReuse.java +++ b/test/jdk/jdk/jfr/api/consumer/filestream/TestReuse.java @@ -89,7 +89,7 @@ public class TestReuse { es.setReuse(true); es.onEvent(e -> { if(events.containsKey(e)) { - success.set(true);; + success.set(true); es.close(); } events.put(e,e); diff --git a/test/jdk/jdk/jfr/api/recording/event/TestEventTime.java b/test/jdk/jdk/jfr/api/recording/event/TestEventTime.java index af740a6e559718b38e9ceec64aef914968a0a786..7ee9748520a7925ae025113d8b65070bf0aaac5b 100644 --- a/test/jdk/jdk/jfr/api/recording/event/TestEventTime.java +++ b/test/jdk/jdk/jfr/api/recording/event/TestEventTime.java @@ -101,7 +101,7 @@ public class TestEventTime { MyEvent event = new MyEvent(id); event.begin(); if (!CommonHelper.hasFastTimeEnabled()) { - CommonHelper.waitForSystemCurrentMillisToChange();; + CommonHelper.waitForSystemCurrentMillisToChange(); } actualOrder.add(new TimeEvent(id, true)); return event; @@ -110,7 +110,7 @@ public class TestEventTime { private static void endEvent(MyEvent event) throws Exception { event.end(); if (!CommonHelper.hasFastTimeEnabled()) { - CommonHelper.waitForSystemCurrentMillisToChange();; + CommonHelper.waitForSystemCurrentMillisToChange(); } event.commit(); actualOrder.add(new TimeEvent(event.id, false)); diff --git a/test/jdk/jdk/jfr/event/runtime/TestActiveSettingEvent.java b/test/jdk/jdk/jfr/event/runtime/TestActiveSettingEvent.java index 5be87e78e10b1a793c550ef1c6fa5933f6def9ea..7f6f7be79d2752ccbca94d0b4c7edf8218857c87 100644 --- a/test/jdk/jdk/jfr/event/runtime/TestActiveSettingEvent.java +++ b/test/jdk/jdk/jfr/event/runtime/TestActiveSettingEvent.java @@ -58,8 +58,8 @@ public final class TestActiveSettingEvent { private static final String ACTIVE_SETTING_EVENT_NAME = EventNames.ActiveSetting; public static void main(String[] args) throws Throwable { - testDefaultSettings();; - testProfileSettings();; + testDefaultSettings(); + testProfileSettings(); testNewSettings(); testChangedSetting(); testUnregistered(); diff --git a/test/jdk/jdk/jfr/jvm/TestWaste.java b/test/jdk/jdk/jfr/jvm/TestWaste.java new file mode 100644 index 0000000000000000000000000000000000000000..0cc1010765eb633cbba83d77deb2b5e9195f83ee --- /dev/null +++ b/test/jdk/jdk/jfr/jvm/TestWaste.java @@ -0,0 +1,128 @@ +/* + * 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 jdk.jfr.Recording; +import jdk.jfr.Event; +import jdk.jfr.consumer.RecordingFile; +import jdk.jfr.internal.test.WhiteBox; + +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.HashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Random; + +import jdk.jfr.Configuration; + +/** + * @test + * @key jfr + * @requires vm.hasJFR + * @library /test/lib /test/jdk + * @modules jdk.jfr/jdk.jfr.internal.test + * @run main/othervm -XX:TLABSize=2k jdk.jfr.jvm.TestWaste + */ +public class TestWaste { + static List list = new LinkedList<>(); + static Random random = new Random(); + + public static void main(String... args) throws Exception { + WhiteBox.setWriteAllObjectSamples(true); + Configuration c = Configuration.getConfiguration("profile"); + Path file = Path.of("recording.jfr"); + Path scrubbed = Path.of("scrubbed.jfr"); + try (Recording r = new Recording(c)) { + // Old objects that are cleared out should not create waste + r.enable("jdk.OldObjectSample") + .with("cutoff", "infinity") + .withStackTrace(); + // No stack trace waste from allocation sample + r.enable("jdk.ObjectAllocationSample") + .with("throttle", "1000/s") + .withoutStackTrace(); + // Unused threads should not create unreasonable amount of waste + r.disable("jdk.ThreadStart"); + r.disable("jdk.ThreadStop"); + // jdk.GCPhaseParallel can often, but not always, take up a very + // large part of the recording. Disable to make test more stable + r.disable("jdk.GCPhaseParallel"); + r.start(); + // Generate data + for (int i = 0; i < 5_000_000; i++) { + foo(50); + if (i % 3_000_000 == 0) { + System.gc(); + } + if (i % 10_000 == 0) { + Thread t = new Thread(); + t.start(); + } + } + r.stop(); + r.dump(file); + final Map histogram = new HashMap<>(); + try (RecordingFile rf = new RecordingFile(file)) { + rf.write(scrubbed, event -> { + String key = event.getEventType().getName(); + histogram.merge(key, 1L, (x, y) -> x + y); + return true; + }); + } + for (var entry : histogram.entrySet()) { + System.out.println(entry.getKey() + " " + entry.getValue()); + } + float fileSize = Files.size(file); + System.out.printf("File size: %.2f MB\n", fileSize / (1024 * 1024)); + float scrubbedSize = Files.size(scrubbed); + System.out.printf("Scrubbed size: %.2f MB\n", scrubbedSize / (1024 * 1024)); + float waste = 1 - scrubbedSize / fileSize; + System.out.printf("Waste: %.2f%%\n", 100 * waste); + if (waste > 0.10) { + throw new AssertionError("Found more than 10% waste"); + } + } + } + + static void foo(int depth) { + bar(depth - 1); + } + + static void bar(int depth) { + if (depth > 1) { + if (random.nextBoolean()) { + foo(depth); + } else { + bar(depth - 1); + } + } else { + list.add(new String("hello")); + } + } +} diff --git a/test/jdk/jdk/jfr/tool/TestScrub.java b/test/jdk/jdk/jfr/tool/TestScrub.java new file mode 100644 index 0000000000000000000000000000000000000000..32b1767cf7d5ef7af6d6935f275e22171e6b5e57 --- /dev/null +++ b/test/jdk/jdk/jfr/tool/TestScrub.java @@ -0,0 +1,313 @@ +/* + * 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.tool; + +import java.io.FileWriter; +import java.io.IOException; +import java.lang.reflect.InvocationTargetException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import jdk.test.lib.Utils; +import jdk.test.lib.process.OutputAnalyzer; +import jdk.jfr.Name; +import jdk.jfr.Recording; +import jdk.jfr.Category; +import jdk.jfr.Event; +import jdk.jfr.consumer.RecordedEvent; +import jdk.jfr.consumer.RecordingFile; + +/** + * @test + * @summary Test jfr scrub + * @key jfr + * @requires vm.hasJFR + * @library /test/lib /test/jdk + * @run main/othervm jdk.jfr.tool.TestScrub + */ +public class TestScrub { + + @Name("example.Tiger") + @Category("Mammal") + private static class TigerEvent extends Event { + } + + @Name("example.Zebra") + @Category("Mammal") + + private static class ZebraEvent extends Event { + } + + @Name("example.Tigerfish") + @Category("Fish") + private static class TigerfishEvent extends Event { + } + + public static void main(String[] args) throws Throwable { + Path file = Path.of("recording.jfr"); + Path autogenerated = Path.of("recording-scrubbed.jfr"); + + try (Recording r = new Recording()) { + r.start(); + emit(100, "India", TigerEvent.class); + emit(100, "Namibia", ZebraEvent.class); + emit(10000, "Lake Tanganyika", TigerfishEvent.class); + r.stop(); + r.dump(file); + } + testAutogeneratedFilename(file, autogenerated); + + testEventInclude(file); + testEventExclude(file); + testEventMixedIncludeExclude(file); + + testCategoryExclude(file); + testCategoryInclude(file); + + testThreadExclude(file); + testThreadInclude(file); + } + + private static void testAutogeneratedFilename(Path file, Path autogenerated) throws Throwable { + List arguments = new ArrayList<>(); + arguments.add("scrub"); + arguments.add(file.toAbsolutePath().toString()); + ExecuteHelper.jfr(arguments.toArray(String[]::new)); + + if (!Files.exists(autogenerated)) { + throw new AssertionError("Expected to find auto-generated file " + autogenerated); + } + Files.delete(autogenerated); + } + + private static void testEventInclude(Path file) throws Throwable { + for (var event : scrub(file, "--include-events", "Zebra")) { + assertEvent(event, "Zebra"); + assertNotEvent(event, "Tiger", "Tigerfish"); + } + for (var event : scrub(file, "--include-events", "Tiger*")) { + assertEvent(event, "Tiger", "Tigerfish"); + assertNotEvent(event, "Zebra"); + } + for (var event : scrub(file, "--include-events", "Tiger,Zebra")) { + assertEvent(event, "Tiger", "Zebra"); + assertNotEvent(event, "Tigerfish"); + } + for (var event : scrub(file, "--include-events", "Tiger", "--include-events", "Zebra")) { + assertEvent(event, "Tiger", "Zebra"); + assertNotEvent(event, "Tigerfish"); + } + } + + private static void testEventExclude(Path file) throws Throwable { + for (var event : scrub(file, "--exclude-events", "Zebra")) { + assertNotEvent(event, "Zebra"); + assertEvent(event, "Tiger", "Tigerfish"); + } + for (var event : scrub(file, "--exclude-events", "Tiger*")) { + assertEvent(event, "Zebra"); + assertNotEvent(event, "Tiger", "Tigerfish"); + } + for (var event : scrub(file, "--exclude-events", "Tiger,Zebra")) { + assertEvent(event, "Tigerfish"); + assertNotEvent(event, "Tiger", "Zebra"); + } + + for (var event : scrub(file, "--exclude-events", "Tiger", "--exclude-events", "Zebra")) { + assertEvent(event, "Tigerfish"); + assertNotEvent(event, "Tiger", "Zebra"); + } + } + + private static void testEventMixedIncludeExclude(Path file) throws Throwable { + for (var event : scrub(file, "--include-events", "Tiger*", "--exclude-events", "Tigerfish")) { + assertNotEvent(event, "Zebra", "Tigerfish"); + assertEvent(event, "Tiger"); + } + for (var event : scrub(file, "--exclude-events", "Tiger*", "--include-events", "Tiger")) { + assertEvent(event, "Zebra", "Tiger"); + assertNotEvent(event, "Tigerfish"); + } + for (var event : scrub(file, "--exclude-events", "example.*", "--include-events", "example.*")) { + assertNotEvent(event, "Tigerfish", "Tiger", "Zebra"); + } + for (var event : scrub(file, "--include-events", "example.*", "--exclude-events", "example.*")) { + assertNotEvent(event, "Tigerfish", "Tiger", "Zebra"); + } + } + + private static void testCategoryInclude(Path file) throws Throwable { + for (var event : scrub(file, "--include-categories", "Mammal")) { + assertEvent(event, "Zebra", "Tiger"); + assertNotEvent(event, "Tigerfish"); + } + for (var event : scrub(file, "--include-categories", "Sahara")) { + assertNotEvent(event, "Tiger", "Tigerfish", "Zebra"); + } + for (var event : scrub(file, "--include-categories", "Fish,Mammal")) { + assertEvent(event, "Tiger", "Zebra", "Tigerfish"); + } + for (var event : scrub(file, "--include-categories", "Mammal", "--include-categories", "Fish")) { + assertEvent(event, "Tiger", "Zebra", "Tigerfish"); + } + } + + private static void testCategoryExclude(Path file) throws Throwable { + for (var event : scrub(file, "--exclude-categories", "Mammal")) { + assertNotEvent(event, "Zebra", "Tiger"); + assertEvent(event, "Tigerfish"); + } + for (var event : scrub(file, "--exclude-categories", "Mammal,Fish")) { + assertNotEvent(event, "Zebra", "Tiger", "Tigerfish"); + } + for (var event : scrub(file, "--exclude-categories", "Mammal")) { + assertNotEvent(event, "Zebra", "Tiger"); + assertEvent(event, "Tigerfish"); + } + for (var event : scrub(file, "--exclude-categories", "Mammal")) { + assertNotEvent(event, "Zebra", "Tiger"); + assertEvent(event, "Tigerfish"); + } + } + + private static void testThreadInclude(Path file) throws Throwable { + for (var event : scrub(file, "--include-threads", "Namibia")) { + assertThread(event, "Namibia"); + assertNotThread(event, "India", "Lake Tanganyika"); + } + + for (var event : scrub(file, "--include-threads", "Nam*")) { + assertThread(event, "Namibia"); + assertNotThread(event, "Lake Tanganyika", "India"); + } + + for (var event : scrub(file, "--include-threads", "Namibia,Lake")) { + assertThread(event, "Namibia", "Lake Tanganyika"); + assertNotThread(event, "India"); + } + + for (var event : scrub(file, "--include-threads", "India", "--include-threads", "Lake Tanganyika")) { + assertThread(event, "India", "Lake Tanganyika"); + assertNotThread(event, "Namibia"); + } + } + + private static void testThreadExclude(Path file) throws Throwable { + for (var event : scrub(file, "--exclude-threads", "Namibia")) { + assertThread(event, "India", "Lake Tanganyika"); + assertNotThread(event, "Namibia"); + } + + for (var event : scrub(file, "--exclude-threads", "Nam*")) { + assertThread(event, "Lake Tanganyika", "India"); + assertNotThread(event, "Namibia"); + } + + for (var event : scrub(file, "--exclude-threads", "Namibia,Lake Tanganyika")) { + assertThread(event, "India"); + assertNotThread(event, "Namibia", "Lake Tanganyika"); + } + + for (var event : scrub(file, "--exclude-events", "India", "--include-events", "Lake Tanganyika")) { + assertThread(event, "Namibia"); + assertNotThread(event, "India", "Lake Tanganyika"); + } + } + + private static void assertNotThread(RecordedEvent event, String... threadNames) { + String s = event.getThread().getJavaName(); + for (String threadName : threadNames) { + if (threadName.equals(s)) { + throw new AssertionError("Found unexpected thread" + threadName); + } + } + } + + private static void assertThread(RecordedEvent event, String... threadNames) { + String s = event.getThread().getJavaName(); + for (String threadName : threadNames) { + if (threadName.equals(s)) { + return; + } + } + throw new AssertionError("Found unexpected thread" + s); + } + + private static void assertNotEvent(RecordedEvent event, String... eventNames) { + String s = event.getEventType().getName(); + for (String eventName : eventNames) { + String n = "example." + eventName; + if (n.equals(s)) { + throw new AssertionError("Found unexpected " + eventName + " event"); + } + } + } + + private static void assertEvent(RecordedEvent event, String... eventNames) { + String s = event.getEventType().getName(); + for (String eventName : eventNames) { + String n = "example." + eventName; + if (n.equals(s)) { + return; + } + } + throw new AssertionError("Found unexpected " + s + " event"); + } + + private static List scrub(Path input, String... options) throws Throwable { + Path output = Path.of("scrubbed.jfr"); + List arguments = new ArrayList<>(); + arguments.add("scrub"); + arguments.addAll(Arrays.asList(options)); + arguments.add(input.toAbsolutePath().toString()); + arguments.add(output.toAbsolutePath().toString()); + + var outp = ExecuteHelper.jfr(arguments.toArray(String[]::new)); + System.out.println(outp.getStderr()); + System.out.println(outp.getStdout()); + List events = RecordingFile.readAllEvents(output); + Files.delete(output); + return events; + } + + private static void emit(int count, String threadName, Class eventClass) throws Throwable { + Thread t = new Thread(() -> emitEvents(count, eventClass), threadName); + t.start(); + t.join(); + } + + private static void emitEvents(int count, Class eventClass) { + for (int i = 0; i < count; i++) { + try { + Event event = eventClass.getDeclaredConstructor().newInstance(); + event.commit(); + } catch (Exception e) { + e.printStackTrace(); + } + } + } +} diff --git a/test/jdk/jdk/nio/zipfs/TestPosix.java b/test/jdk/jdk/nio/zipfs/TestPosix.java index 2be70758fbc99cba17c0a58b054043c4b6c6ae22..f629dfef2225d050cb1cb3685471b94964fc3fbd 100644 --- a/test/jdk/jdk/nio/zipfs/TestPosix.java +++ b/test/jdk/jdk/nio/zipfs/TestPosix.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2021, SAP SE. All rights reserved. + * Copyright (c) 2019, 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 @@ -69,11 +69,11 @@ import static org.testng.Assert.fail; /** * @test * @bug 8213031 8273935 + * @summary Test POSIX ZIP file operations. * @modules jdk.zipfs * jdk.jartool * @run testng TestPosix * @run testng/othervm/java.security.policy=test.policy.posix TestPosix - * @summary Test POSIX zip file operations. */ public class TestPosix { private static final ToolProvider JAR_TOOL = ToolProvider.findFirst("jar") @@ -528,9 +528,11 @@ public class TestPosix { } // check entries on copied zipfs - no permission data should exist - try (FileSystem zip = FileSystems.newFileSystem(ZIP_FILE_COPY, ENV_DEFAULT)) { - checkEntries(zip, checkExpects.noPermDataInZip); - } + if (System.getProperty("os.name").toLowerCase().contains("windows")) + try (FileSystem zip = FileSystems.newFileSystem(ZIP_FILE_COPY, + ENV_DEFAULT)) { + checkEntries(zip, checkExpects.noPermDataInZip); + } } /** diff --git a/test/jdk/jdk/nio/zipfs/test.policy b/test/jdk/jdk/nio/zipfs/test.policy index 1e91f1f8dcf9174a84cd1e70fb965621042c15c5..d0492d0fc7a142212a436f84d1080221d6649e9e 100644 --- a/test/jdk/jdk/nio/zipfs/test.policy +++ b/test/jdk/jdk/nio/zipfs/test.policy @@ -3,4 +3,5 @@ grant { permission java.util.PropertyPermission "test.jdk","read"; permission java.util.PropertyPermission "test.src","read"; permission java.util.PropertyPermission "user.dir","read"; + permission java.lang.RuntimePermission "accessUserInformation"; }; diff --git a/test/jdk/jdk/nio/zipfs/test.policy.posix b/test/jdk/jdk/nio/zipfs/test.policy.posix index 601ef439ab4af23a4e5d0d449c0427cdc8971a1b..77415b0f4ba13d5651b9e5d29b53ed541a44302d 100644 --- a/test/jdk/jdk/nio/zipfs/test.policy.posix +++ b/test/jdk/jdk/nio/zipfs/test.policy.posix @@ -5,4 +5,5 @@ grant { permission java.util.PropertyPermission "test.src","read"; permission java.util.PropertyPermission "user.dir","read"; permission java.lang.RuntimePermission "accessClassInPackage.jdk.internal.module"; + permission java.lang.RuntimePermission "accessUserInformation"; }; diff --git a/test/jdk/lib/testlibrary/java/lang/UCDFiles.java b/test/jdk/lib/testlibrary/java/lang/UCDFiles.java index 10c6243f6150f7780b5f80a5664f020b27aae0cf..83054c5c0fb05bd12c9b3fc7ae63b59d34b7e39c 100644 --- a/test/jdk/lib/testlibrary/java/lang/UCDFiles.java +++ b/test/jdk/lib/testlibrary/java/lang/UCDFiles.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 @@ -23,16 +23,15 @@ /** * Holds the file paths to the Unicode Character Database source files. - * Paths to the source files in the "make" directory are relative, and - * subject to change due to future repository structure re-org. + * Paths to the source files in the "data" directory are relative. */ import java.nio.file.Path; import java.nio.file.Paths; public class UCDFiles { - public static Path UCD_DIR = Paths.get( - System.getProperty("test.root"), "..", "..", "make", "data", "unicodedata"); + public static Path UCD_DIR = Paths.get(System.getProperty("test.root"), + "../../src/java.base/share/data/unicodedata"); public static Path BLOCKS = UCD_DIR.resolve("Blocks.txt"); diff --git a/test/jdk/sanity/client/lib/SwingSet3/src/com/sun/swingset3/demos/tooltip/ToolTipDemo.java b/test/jdk/sanity/client/lib/SwingSet3/src/com/sun/swingset3/demos/tooltip/ToolTipDemo.java index 724a16715bb2d48f577f50d8502aa6e17dee035a..105160237ccef5c203929a869cc8ba759403bf16 100644 --- a/test/jdk/sanity/client/lib/SwingSet3/src/com/sun/swingset3/demos/tooltip/ToolTipDemo.java +++ b/test/jdk/sanity/client/lib/SwingSet3/src/com/sun/swingset3/demos/tooltip/ToolTipDemo.java @@ -58,9 +58,9 @@ public class ToolTipDemo extends JPanel { public static final String DEMO_TITLE = ToolTipDemo.class.getAnnotation(DemoProperties.class).value(); private final static ResourceManager resourceManager = new ResourceManager(ToolTipDemo.class); - public static final String PLAIN_TOOLTIP_COMP_TITLE = resourceManager.getString("ToolTipDemo.plain");; + public static final String PLAIN_TOOLTIP_COMP_TITLE = resourceManager.getString("ToolTipDemo.plain"); public static final String PLAIN_TOOLTIP_TEXT = "A simple one line tip."; - public static final String HTML_TOOLTIP_COMP_TITLE = resourceManager.getString("ToolTipDemo.html");; + public static final String HTML_TOOLTIP_COMP_TITLE = resourceManager.getString("ToolTipDemo.html"); public static final String HTML_TOOLTIP_TEXT = "In case you thought that tooltips had to be

" + "boring, one line descriptions, the Swing! team

" + "is happy to shatter your illusions.

" + diff --git a/test/jdk/sun/java2d/DirectX/MultiPaintEventTest/MultiPaintEventTest.java b/test/jdk/sun/java2d/DirectX/MultiPaintEventTest/MultiPaintEventTest.java new file mode 100644 index 0000000000000000000000000000000000000000..27d54af6a0be703f5b7f323045aa458bfaba7635 --- /dev/null +++ b/test/jdk/sun/java2d/DirectX/MultiPaintEventTest/MultiPaintEventTest.java @@ -0,0 +1,86 @@ +/* + * 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/cmm/ColorConvertOp/ImageFactory.java b/test/jdk/sun/java2d/cmm/ColorConvertOp/ImageFactory.java index a16f37f1236503c2fa140b9a2733aee2837c2615..62cc0f527206ca36bcc9b2b9fdab05cb1e7de399 100644 --- a/test/jdk/sun/java2d/cmm/ColorConvertOp/ImageFactory.java +++ b/test/jdk/sun/java2d/cmm/ColorConvertOp/ImageFactory.java @@ -258,7 +258,7 @@ public class ImageFactory { for (int j = 0; j < HEIGHT; j++) { pixel[0] = (i/255.0)*(cs.getMaxValue(0) - cs.getMinValue(0)) + - cs.getMinValue(0);; + cs.getMinValue(0); sm.setPixel(i, j, pixel, data); } } @@ -268,7 +268,7 @@ public class ImageFactory { for (int j = 0; j < HEIGHT; j++) { pixel[0] = (i/255.0f)*(cs.getMaxValue(0) - cs.getMinValue(0)) + - cs.getMinValue(0);; + cs.getMinValue(0); sm.setPixel(i, j, pixel, data); } } diff --git a/test/jdk/sun/management/PlatformMBeanProviderConstructorCheck.java b/test/jdk/sun/management/PlatformMBeanProviderConstructorCheck.java index b7b4edc8c98061b1230aff09536f710e3fff722c..16fee912a7c29d9b6fbb8544f138a23aaf90a5fe 100644 --- a/test/jdk/sun/management/PlatformMBeanProviderConstructorCheck.java +++ b/test/jdk/sun/management/PlatformMBeanProviderConstructorCheck.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 @@ -21,63 +21,79 @@ * questions. */ -import java.security.AccessControlException; -import java.security.Permission; -import java.security.Policy; -import java.security.ProtectionDomain; +import java.lang.management.ManagementFactory; +import java.lang.management.RuntimeMXBean; import java.util.List; +import jdk.test.lib.process.OutputAnalyzer; +import jdk.test.lib.process.ProcessTools; + +import static jdk.test.lib.Asserts.*; + /* * @test - * @bug 8042901 - * @summary Check permission for PlatformMBeanProvider Constructor + * @library /test/lib + * @build jdk.test.lib.Asserts + * @bug 8042901 8283092 + * @summary Check encapsulation of PlatformMBeanProvider Constructor * @modules java.management/sun.management.spi - * @author Shanliang Jiang - * @run main/othervm -Djava.security.manager=allow PlatformMBeanProviderConstructorCheck + * @run main PlatformMBeanProviderConstructorCheck */ public class PlatformMBeanProviderConstructorCheck { - public static void main(String[] args) throws Exception { - Policy origPolicy = Policy.getPolicy(); - SecurityManager origSM = System.getSecurityManager(); - try { - System.out.println("---PlatformMBeanProviderConstructorCheck starting..."); - Policy.setPolicy(new MyPolicy()); - System.setSecurityManager(new SecurityManager()); + /** + * jtreg invokes this test with module arguments that permit compilation + * of the MyProvider class, which extends PlatformMBeanProvider. + * First check we can invoke that class, then re-invoke ourself without + * those module arguments, and expect a failure calling MyProvider. + */ + public static void main(String[] args) throws Exception { + System.out.println("---PlatformMBeanProviderConstructorCheck:"); + boolean expectedFail = false; - System.out.println("---PlatformMBeanProviderConstructorCheck Testing without permission..."); - try { - new MyProvider(); - throw new RuntimeException("Does not get expected AccessControlException!"); - } catch (AccessControlException ace) { - System.out.println("---PlatformMBeanProviderConstructorCheck got the expected exception: " - + ace); + // Recognise argument to signify we were re-invoked, and MyProvider should fail: + if (args.length == 1) { + if (args[0].equals("--nomoduleargs")) { + expectedFail = true; + verifyNoModuleArguments(); + } else { + throw new RuntimeException("unknown argument: '" + args[0] + "'"); } - - System.out.println("---PlatformMBeanProviderConstructorCheck Testing with permission..."); - MyPolicy.allowed = true; + } + System.out.println("---PlatformMBeanProviderConstructorCheck: invoke MyProvider with expectedFail = " + expectedFail); + Throwable e = null; + try { new MyProvider(); - - System.out.println("---PlatformMBeanProviderConstructorCheck PASSED!"); - } finally { - System.setSecurityManager(origSM); - Policy.setPolicy(origPolicy); + } catch (IllegalAccessError iae) { + System.out.println("---PlatformMBeanProviderConstructorCheck got exception: " + iae); + e = iae; } - } - private static class MyPolicy extends Policy { - private static String permName = "sun.management.spi.PlatformMBeanProvider.subclass"; - private static boolean allowed = false; + if (!expectedFail) { + // This was the first invocation, should have worked OK: + assertNull(e); + System.out.println("---PlatformMBeanProviderConstructorCheck PASSED (1) (expectedFail = " + expectedFail + ")"); - @Override - public boolean implies(ProtectionDomain domain, Permission permission) { - if (permName.equals(permission.getName())) { - System.out.println("---MyPolicy-implies checks permission for " - +permName+" and returns "+allowed); + // Re-invoke this test to check failure: + System.out.println("---PlatformMBeanProviderConstructorCheck: re-invoke without --add-modules or --add-exports"); + OutputAnalyzer output = ProcessTools.executeTestJava("PlatformMBeanProviderConstructorCheck", "--nomoduleargs"); + output.reportDiagnosticSummary(); + output.shouldContain("java.lang.IllegalAccessError: superclass access check failed:"); + output.shouldContain(" module java.management does not export sun.management.spi to "); + output.shouldNotContain("MyProvider constructor."); + } else { + // This was the re-invocation without module access, should fail: + assertNotNull(e); + System.out.println("---PlatformMBeanProviderConstructorCheck PASSED (2) (expectedFail = " + expectedFail + ")"); + } + } - return allowed; - } else { - return true; + private static void verifyNoModuleArguments() { + RuntimeMXBean mxbean = ManagementFactory.getRuntimeMXBean(); + for (String s : mxbean.getInputArguments()) { + if (s.startsWith("--add-modules") || s.startsWith("--add-exports")) { + System.out.println("arg: " + s); + throw new RuntimeException("argument list contains: " + s); } } } @@ -85,6 +101,7 @@ public class PlatformMBeanProviderConstructorCheck { private static class MyProvider extends sun.management.spi.PlatformMBeanProvider { @Override public List> getPlatformComponentList() { + System.out.println("MyProvider constructor."); return null; } } diff --git a/test/jdk/sun/net/www/AuthHeaderTest.java b/test/jdk/sun/net/www/AuthHeaderTest.java index 53852aab8f176e6a88e08cf722fd1310442ad5f5..ba1729cb7e6e7884de97559ce55fd8383e9859df 100644 --- a/test/jdk/sun/net/www/AuthHeaderTest.java +++ b/test/jdk/sun/net/www/AuthHeaderTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2012, 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 @@ -24,53 +24,31 @@ /** * @test * @bug 4804309 - * @modules java.base/sun.net.www - * @library ../../../sun/net/www/httptest/ - * @build HttpCallback TestHttpServer ClosedChannelList HttpTransaction - * @run main AuthHeaderTest + * @library /test/lib + * @run main/othervm AuthHeaderTest * @summary AuthHeaderTest bug */ -import java.io.*; -import java.net.*; - -public class AuthHeaderTest implements HttpCallback { - - static int count = 0; - static String authstring; - - void errorReply (HttpTransaction req, String reply) throws IOException { - req.addResponseHeader ("Connection", "close"); - req.addResponseHeader ("Www-authenticate", reply); - req.sendResponse (401, "Unauthorized"); - req.orderlyClose(); - } - - void okReply (HttpTransaction req) throws IOException { - req.setResponseEntityBody ("Hello ."); - req.sendResponse (200, "Ok"); - req.orderlyClose(); - } - - public void request (HttpTransaction req) { - try { - authstring = req.getRequestHeader ("Authorization"); - System.out.println (authstring); - switch (count) { - case 0: - errorReply (req, "Basic realm=\"wallyworld\""); - break; - case 1: - /* client stores a username/pw for wallyworld - */ - okReply (req); - break; - } - count ++; - } catch (IOException e) { - e.printStackTrace(); - } - } +import java.io.IOException; +import java.io.InputStream; +import java.io.PrintWriter; +import java.net.Authenticator; +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.net.PasswordAuthentication; +import java.net.Proxy; +import java.net.URL; +import java.net.URLConnection; +import java.nio.charset.Charset; +import java.util.concurrent.Executors; + +import com.sun.net.httpserver.HttpExchange; +import com.sun.net.httpserver.HttpHandler; +import com.sun.net.httpserver.HttpServer; +import jdk.test.lib.net.URIBuilder; + +public class AuthHeaderTest { + static HttpServer server; static void read (InputStream is) throws IOException { int c; @@ -91,19 +69,27 @@ public class AuthHeaderTest implements HttpCallback { is.close(); } - static TestHttpServer server; - public static void main (String[] args) throws Exception { MyAuthenticator auth = new MyAuthenticator (); Authenticator.setDefault (auth); InetAddress loopback = InetAddress.getLoopbackAddress(); try { - server = new TestHttpServer (new AuthHeaderTest(), 1, 10, loopback, 0); - System.out.println ("Server: listening on port: " + server.getAuthority()); - client ("http://" + server.getAuthority() + "/d1/foo.html"); + server = HttpServer.create(new InetSocketAddress(loopback, 0), 10, "/", new AuthHeaderTestHandler()); + server.setExecutor(Executors.newSingleThreadExecutor()); + server.start(); + System.out.println ("Server: listening on port: " + server.getAddress().getPort()); + + String serverURL = URIBuilder.newBuilder() + .scheme("http") + .loopback() + .port(server.getAddress().getPort()) + .path("/") + .build() + .toString(); + client (serverURL + "d1/foo.html"); } catch (Exception e) { if (server != null) { - server.terminate(); + server.stop(1); } throw e; } @@ -111,11 +97,11 @@ public class AuthHeaderTest implements HttpCallback { if (f != 1) { except ("Authenticator was called "+f+" times. Should be 1"); } - server.terminate(); + server.stop(1); } public static void except (String s) { - server.terminate(); + server.stop(1); throw new RuntimeException (s); } @@ -138,3 +124,45 @@ public class AuthHeaderTest implements HttpCallback { } } } + +class AuthHeaderTestHandler implements HttpHandler { + static int count = 0; + static String authstring; + + void errorReply (HttpExchange req, String reply) throws IOException { + req.getResponseHeaders().set("Connection", "close"); + req.getResponseHeaders().set("Www-authenticate", reply); + req.sendResponseHeaders(401, -1); + } + + void okReply (HttpExchange req) throws IOException { + req.sendResponseHeaders (200, 0); + try(PrintWriter pw = new PrintWriter(req.getResponseBody(), false, Charset.forName("UTF-8"))) { + pw.print("Hello ."); + } + } + + @Override + public void handle(HttpExchange exchange) throws IOException { + try { + if(exchange.getRequestHeaders().get("Authorization") != null) { + authstring = exchange.getRequestHeaders().get("Authorization").get(0); + System.out.println (authstring); + } + + switch (count) { + case 0: + errorReply (exchange, "Basic realm=\"wallyworld\""); + break; + case 1: + /* client stores a username/pw for wallyworld + */ + okReply (exchange); + break; + } + count ++; + } catch (IOException e) { + e.printStackTrace(); + } + } +} \ No newline at end of file diff --git a/test/jdk/sun/net/www/http/KeepAliveCache/B5045306.java b/test/jdk/sun/net/www/http/KeepAliveCache/B5045306.java index d624741bc2ccd16be21bed6782fea29094f72b1c..ebfb550b8263406595fe0aafebc24b24350f0259 100644 --- a/test/jdk/sun/net/www/http/KeepAliveCache/B5045306.java +++ b/test/jdk/sun/net/www/http/KeepAliveCache/B5045306.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 @@ -24,19 +24,30 @@ /* * @test * @bug 5045306 6356004 6993490 8255124 - * @modules java.base/sun.net.www - * java.management - * @library ../../httptest/ - * @build HttpCallback TestHttpServer HttpTransaction + * @library /test/lib * @run main/othervm B5045306 * @summary Http keep-alive implementation is not efficient */ -import java.net.*; -import java.io.*; -import java.lang.management.*; +import java.io.IOException; +import java.io.InputStream; +import java.io.PrintWriter; +import java.lang.management.ManagementFactory; +import java.lang.management.ThreadInfo; +import java.lang.management.ThreadMXBean; +import java.net.HttpURLConnection; +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.net.Proxy; +import java.net.URL; +import java.nio.charset.Charset; import java.util.ArrayList; import java.util.List; +import java.util.concurrent.Executors; + +import com.sun.net.httpserver.HttpExchange; +import com.sun.net.httpserver.HttpHandler; +import com.sun.net.httpserver.HttpServer; /* Part 1: * The http client makes a connection to a URL whos content contains a lot of @@ -51,20 +62,19 @@ import java.util.List; * Content-length header. */ -public class B5045306 -{ - static SimpleHttpTransaction httpTrans; - static TestHttpServer server; +public class B5045306 { + static HttpServer server; - public static void main(String[] args) throws Exception { + public static void main(String[] args) { startHttpServer(); clientHttpCalls(); } public static void startHttpServer() { try { - httpTrans = new SimpleHttpTransaction(); - server = new TestHttpServer(httpTrans, 1, 10, InetAddress.getLocalHost(), 0); + server = HttpServer.create(new InetSocketAddress(InetAddress.getLocalHost(), 0), 10, "/", new SimpleHttpTransactionHandler()); + server.setExecutor(Executors.newSingleThreadExecutor()); + server.start(); } catch (IOException e) { e.printStackTrace(); } @@ -76,10 +86,10 @@ public class B5045306 uncaught.add(ex); }); try { - System.out.println("http server listen on: " + server.getLocalPort()); + System.out.println("http server listen on: " + server.getAddress().getPort()); String hostAddr = InetAddress.getLocalHost().getHostAddress(); if (hostAddr.indexOf(':') > -1) hostAddr = "[" + hostAddr + "]"; - String baseURLStr = "http://" + hostAddr + ":" + server.getLocalPort() + "/"; + String baseURLStr = "http://" + hostAddr + ":" + server.getAddress().getPort() + "/"; URL bigDataURL = new URL (baseURLStr + "firstCall"); URL smallDataURL = new URL (baseURLStr + "secondCall"); @@ -98,7 +108,7 @@ public class B5045306 uc = (HttpURLConnection)smallDataURL.openConnection(Proxy.NO_PROXY); uc.getResponseCode(); - if (SimpleHttpTransaction.failed) + if (SimpleHttpTransactionHandler.failed) throw new RuntimeException("Failed: Initial Keep Alive Connection is not being reused"); // Part 2 @@ -137,7 +147,7 @@ public class B5045306 } catch (IOException e) { e.printStackTrace(); } finally { - server.terminate(); + server.stop(1); } if (!uncaught.isEmpty()) { throw new RuntimeException("Unhandled exception:", uncaught.get(0)); @@ -145,9 +155,9 @@ public class B5045306 } } -class SimpleHttpTransaction implements HttpCallback +class SimpleHttpTransactionHandler implements HttpHandler { - static boolean failed = false; + static volatile boolean failed = false; // Need to have enough data here that is too large for the socket buffer to hold. // Also http.KeepAlive.remainingData must be greater than this value, default is 256K. @@ -155,48 +165,46 @@ class SimpleHttpTransaction implements HttpCallback int port1; - public void request(HttpTransaction trans) { + public void handle(HttpExchange trans) { try { String path = trans.getRequestURI().getPath(); if (path.equals("/firstCall")) { - port1 = trans.channel().socket().getPort(); + port1 = trans.getLocalAddress().getPort(); System.out.println("First connection on client port = " + port1); byte[] responseBody = new byte[RESPONSE_DATA_LENGTH]; for (int i=0; i total_len) { - byte[] total1 = new byte [total_len * 2]; - System.arraycopy (total, 0, total1, 0, len); - total = total1; - total_len = total_len * 2; - } - System.arraycopy (buf, 0, total, len, c); - len += c; - } - setResponseEntityBody (total, len); - } - - /* chunked */ - - /** - * Set the entity response body with the given array of strings - * The content encoding is set to "chunked" and each array element - * is sent as one chunk. - * @param body the array of string chunks to send in the response - */ - public void setResponseEntityBody (String[] body) { - StringBuffer buf = new StringBuffer (); - int len = 0; - for (int i=0; i - * It must be instantiated with a {@link HttpCallback} object to which - * requests are given and must be handled. - *

- * Simple synchronization between the client(s) and server can be done - * using the {@link #waitForCondition(String)}, {@link #setCondition(String)} and - * {@link #rendezvous(String,int)} methods. - * - * NOTE NOTE NOTE NOTE NOTE NOTE NOTE - * - * If changes are made here, please sure they are propagated to - * the HTTPS equivalent in the JSSE regression test suite. - * - * NOTE NOTE NOTE NOTE NOTE NOTE NOTE - */ - -public class TestHttpServer { - - ServerSocketChannel schan; - int threads; - int cperthread; - HttpCallback cb; - Server[] servers; - - /** - * Create a TestHttpServer instance with the specified callback object - * for handling requests. One thread is created to handle requests, - * and up to ten TCP connections will be handled simultaneously. - * @param cb the callback object which is invoked to handle each - * incoming request - */ - - public TestHttpServer (HttpCallback cb) throws IOException { - this (cb, 1, 10, 0); - } - - /** - * Create a TestHttpServer instance with the specified callback object - * for handling requests. One thread is created to handle requests, - * and up to ten TCP connections will be handled simultaneously. - * @param cb the callback object which is invoked to handle each - * incoming request - * @param address the address to bind the server to. Null - * means bind to the wildcard address. - * @param port the port number to bind the server to. Zero - * means choose any free port. - */ - - public TestHttpServer (HttpCallback cb, InetAddress address, int port) throws IOException { - this (cb, 1, 10, address, 0); - } - - /** - * Create a TestHttpServer instance with the specified number of - * threads and maximum number of connections per thread. This functions - * the same as the 4 arg constructor, where the port argument is set to zero. - * @param cb the callback object which is invoked to handle each - * incoming request - * @param threads the number of threads to create to handle requests - * in parallel - * @param cperthread the number of simultaneous TCP connections to - * handle per thread - */ - - public TestHttpServer (HttpCallback cb, int threads, int cperthread) - throws IOException { - this (cb, threads, cperthread, 0); - } - - /** - * Create a TestHttpServer instance with the specified number - * of threads and maximum number of connections per thread and running on - * the specified port. The specified number of threads are created to - * handle incoming requests, and each thread is allowed - * to handle a number of simultaneous TCP connections. - * @param cb the callback object which is invoked to handle - * each incoming request - * @param threads the number of threads to create to handle - * requests in parallel - * @param cperthread the number of simultaneous TCP connections - * to handle per thread - * @param port the port number to bind the server to. Zero - * means choose any free port. - */ - - public TestHttpServer (HttpCallback cb, int threads, int cperthread, int port) - throws IOException { - this(cb, threads, cperthread, null, port); - } - - /** - * Create a TestHttpServer instance with the specified number - * of threads and maximum number of connections per thread and running on - * the specified port. The specified number of threads are created to - * handle incoming requests, and each thread is allowed - * to handle a number of simultaneous TCP connections. - * @param cb the callback object which is invoked to handle - * each incoming request - * @param threads the number of threads to create to handle - * requests in parallel - * @param cperthread the number of simultaneous TCP connections - * to handle per thread - * @param address the address to bind the server to. Null - * means bind to the wildcard address. - * @param port the port number to bind the server to. Zero - * means choose any free port. - */ - - public TestHttpServer (HttpCallback cb, int threads, int cperthread, - InetAddress address, int port) - throws IOException { - schan = ServerSocketChannel.open (); - InetSocketAddress addr = new InetSocketAddress (address, port); - schan.socket().bind (addr); - this.threads = threads; - this.cb = cb; - this.cperthread = cperthread; - servers = new Server [threads]; - for (int i=0; i -1) hostaddr = "[" + hostaddr + "]"; - return hostaddr + ":" + getLocalPort(); - } - - static class Server extends Thread { - - ServerSocketChannel schan; - Selector selector; - SelectionKey listenerKey; - SelectionKey key; /* the current key being processed */ - HttpCallback cb; - ByteBuffer consumeBuffer; - int maxconn; - int nconn; - ClosedChannelList clist; - volatile boolean shutdown; - - Server (HttpCallback cb, ServerSocketChannel schan, int maxconn) { - this.schan = schan; - this.maxconn = maxconn; - this.cb = cb; - nconn = 0; - consumeBuffer = ByteBuffer.allocate (512); - clist = new ClosedChannelList (); - try { - selector = Selector.open (); - schan.configureBlocking (false); - listenerKey = schan.register (selector, SelectionKey.OP_ACCEPT); - } catch (IOException e) { - System.err.println ("Server could not start: " + e); - throw new RuntimeException("Server could not start: " + e, e); - } - } - - /* Stop the thread as soon as possible */ - public void terminate () { - shutdown = true; - } - - public void run () { - try { - while (true) { - selector.select(1000); - Set selected = selector.selectedKeys(); - Iterator iter = selected.iterator(); - while (iter.hasNext()) { - key = iter.next(); - if (key.equals (listenerKey)) { - SocketChannel sock = schan.accept (); - if (sock == null) { - /* false notification */ - iter.remove(); - continue; - } - sock.configureBlocking (false); - sock.register (selector, SelectionKey.OP_READ); - nconn ++; - System.out.println("SERVER: new connection. chan[" + sock + "]"); - if (nconn == maxconn) { - /* deregister */ - listenerKey.cancel (); - listenerKey = null; - } - } else { - if (key.isReadable()) { - boolean closed; - SocketChannel chan = (SocketChannel) key.channel(); - System.out.println("SERVER: connection readable. chan[" + chan + "]"); - if (key.attachment() != null) { - System.out.println("Server: consume"); - closed = consume (chan); - } else { - closed = read (chan, key); - } - if (closed) { - chan.close (); - key.cancel (); - if (nconn == maxconn) { - listenerKey = schan.register (selector, SelectionKey.OP_ACCEPT); - } - nconn --; - } - } - } - iter.remove(); - } - clist.check(); - if (shutdown) { - System.out.println("Force to Shutdown"); - SelectionKey sKey = schan.keyFor(selector); - if (sKey != null) { - sKey.cancel(); - } - - clist.terminate (); - selector.close(); - schan.socket().close(); - schan.close(); - return; - } - } - } catch (IOException e) { - System.out.println ("Server exception: " + e); - // TODO finish - } - } - - /* read all the data off the channel without looking at it - * return true if connection closed - */ - boolean consume (SocketChannel chan) { - try { - consumeBuffer.clear (); - int c = chan.read (consumeBuffer); - if (c == -1) - return true; - } catch (IOException e) { - return true; - } - return false; - } - - /* return true if the connection is closed, false otherwise */ - - private boolean read (SocketChannel chan, SelectionKey key) { - HttpTransaction msg; - boolean res; - try { - InputStream is = new BufferedInputStream (new NioInputStream (chan)); - String requestline = readLine (is); - MessageHeader mhead = new MessageHeader (is); - String clen = mhead.findValue ("Content-Length"); - String trferenc = mhead.findValue ("Transfer-Encoding"); - String data = null; - if (trferenc != null && trferenc.equals ("chunked")) - data = new String (readChunkedData (is)); - else if (clen != null) - data = new String (readNormalData (is, Integer.parseInt (clen))); - String[] req = requestline.split (" "); - if (req.length < 2) { - /* invalid request line */ - return false; - } - String cmd = req[0]; - URI uri = null; - try { - uri = new URI (req[1]); - msg = new HttpTransaction (this, cmd, uri, mhead, data, null, key); - cb.request (msg); - } catch (URISyntaxException e) { - System.err.println ("Invalid URI: " + e); - msg = new HttpTransaction (this, cmd, null, null, null, null, key); - msg.sendResponse (501, "Whatever"); - } - res = false; - } catch (IOException e) { - res = true; - } - return res; - } - - byte[] readNormalData (InputStream is, int len) throws IOException { - byte [] buf = new byte [len]; - int c, off=0, remain=len; - while (remain > 0 && ((c=is.read (buf, off, remain))>0)) { - remain -= c; - off += c; - } - return buf; - } - - private void readCRLF(InputStream is) throws IOException { - int cr = is.read(); - int lf = is.read(); - - if (((cr & 0xff) != 0x0d) || - ((lf & 0xff) != 0x0a)) { - throw new IOException( - "Expected : got '" + cr + "/" + lf + "'"); - } - } - - byte[] readChunkedData (InputStream is) throws IOException { - LinkedList l = new LinkedList (); - int total = 0; - for (int len=readChunkLen(is); len!=0; len=readChunkLen(is)) { - l.add (readNormalData(is, len)); - total += len; - readCRLF(is); // CRLF at end of chunk - } - readCRLF(is); // CRLF at end of Chunked Stream. - byte[] buf = new byte [total]; - Iterator i = l.iterator(); - int x = 0; - while (i.hasNext()) { - byte[] b = (byte[])i.next(); - System.arraycopy (b, 0, buf, x, b.length); - x += b.length; - } - return buf; - } - - private int readChunkLen (InputStream is) throws IOException { - int c, len=0; - boolean done=false, readCR=false; - while (!done) { - c = is.read (); - if (c == '\n' && readCR) { - done = true; - } else { - if (c == '\r' && !readCR) { - readCR = true; - } else { - int x=0; - if (c >= 'a' && c <= 'f') { - x = c - 'a' + 10; - } else if (c >= 'A' && c <= 'F') { - x = c - 'A' + 10; - } else if (c >= '0' && c <= '9') { - x = c - '0'; - } - len = len * 16 + x; - } - } - } - return len; - } - - private String readLine (InputStream is) throws IOException { - boolean done=false, readCR=false; - byte[] b = new byte [512]; - int c, l = 0; - - while (!done) { - c = is.read (); - if (c == '\n' && readCR) { - done = true; - } else { - if (c == '\r' && !readCR) { - readCR = true; - } else { - b[l++] = (byte)c; - } - } - } - return new String (b); - } - - /** close the channel associated with the current key by: - * 1. shutdownOutput (send a FIN) - * 2. mark the key so that incoming data is to be consumed and discarded - * 3. After a period, close the socket - */ - - synchronized void orderlyCloseChannel (SelectionKey key) throws IOException { - SocketChannel ch = (SocketChannel)key.channel (); - System.out.println("SERVER: orderlyCloseChannel chan[" + ch + "]"); - ch.socket().shutdownOutput(); - key.attach (this); - clist.add (key); - } - - synchronized void abortiveCloseChannel (SelectionKey key) throws IOException { - SocketChannel ch = (SocketChannel)key.channel (); - System.out.println("SERVER: abortiveCloseChannel chan[" + ch + "]"); - - Socket s = ch.socket (); - s.setSoLinger (true, 0); - ch.close(); - } - } - - - /** - * Implements blocking reading semantics on top of a non-blocking channel - */ - - static class NioInputStream extends InputStream { - SocketChannel channel; - Selector selector; - ByteBuffer chanbuf; - SelectionKey key; - int available; - byte[] one; - boolean closed; - ByteBuffer markBuf; /* reads may be satisifed from this buffer */ - boolean marked; - boolean reset; - int readlimit; - - public NioInputStream (SocketChannel chan) throws IOException { - this.channel = chan; - selector = Selector.open(); - chanbuf = ByteBuffer.allocate (1024); - key = chan.register (selector, SelectionKey.OP_READ); - available = 0; - one = new byte[1]; - closed = marked = reset = false; - } - - public synchronized int read (byte[] b) throws IOException { - return read (b, 0, b.length); - } - - public synchronized int read () throws IOException { - return read (one, 0, 1); - } - - public synchronized int read (byte[] b, int off, int srclen) throws IOException { - - int canreturn, willreturn; - - if (closed) - return -1; - - if (reset) { /* satisfy from markBuf */ - canreturn = markBuf.remaining (); - willreturn = canreturn>srclen ? srclen : canreturn; - markBuf.get(b, off, willreturn); - if (canreturn == willreturn) { - reset = false; - } - } else { /* satisfy from channel */ - canreturn = available(); - if (canreturn == 0) { - block (); - canreturn = available(); - } - willreturn = canreturn>srclen ? srclen : canreturn; - chanbuf.get(b, off, willreturn); - available -= willreturn; - - if (marked) { /* copy into markBuf */ - try { - markBuf.put (b, off, willreturn); - } catch (BufferOverflowException e) { - marked = false; - } - } - } - return willreturn; - } - - public synchronized int available () throws IOException { - if (closed) - throw new IOException ("Stream is closed"); - - if (reset) - return markBuf.remaining(); - - if (available > 0) - return available; - - chanbuf.clear (); - available = channel.read (chanbuf); - if (available > 0) - chanbuf.flip(); - else if (available == -1) - throw new IOException ("Stream is closed"); - return available; - } - - /** - * block() only called when available==0 and buf is empty - */ - private synchronized void block () throws IOException { - //assert available == 0; - int n = selector.select (); - //assert n == 1; - selector.selectedKeys().clear(); - available (); - } - - public void close () throws IOException { - if (closed) - return; - channel.close (); - closed = true; - } - - public synchronized void mark (int readlimit) { - if (closed) - return; - this.readlimit = readlimit; - markBuf = ByteBuffer.allocate (readlimit); - marked = true; - reset = false; - } - - public synchronized void reset () throws IOException { - if (closed ) - return; - if (!marked) - throw new IOException ("Stream not marked"); - marked = false; - reset = true; - markBuf.flip (); - } - } - - static class NioOutputStream extends OutputStream { - SocketChannel channel; - ByteBuffer buf; - SelectionKey key; - Selector selector; - boolean closed; - byte[] one; - - public NioOutputStream (SocketChannel channel) throws IOException { - this.channel = channel; - selector = Selector.open (); - key = channel.register (selector, SelectionKey.OP_WRITE); - closed = false; - one = new byte [1]; - } - - public synchronized void write (int b) throws IOException { - one[0] = (byte)b; - write (one, 0, 1); - } - - public synchronized void write (byte[] b) throws IOException { - write (b, 0, b.length); - } - - public synchronized void write (byte[] b, int off, int len) throws IOException { - if (closed) - throw new IOException ("stream is closed"); - - buf = ByteBuffer.allocate (len); - buf.put (b, off, len); - buf.flip (); - int n; - while ((n = channel.write (buf)) < len) { - len -= n; - if (len == 0) - return; - selector.select (); - selector.selectedKeys().clear (); - } - } - - public void close () throws IOException { - if (closed) - return; - channel.close (); - closed = true; - } - } - - /** - * Utilities for synchronization. A condition is - * identified by a string name, and is initialized - * upon first use (ie. setCondition() or waitForCondition()). Threads - * are blocked until some thread calls (or has called) setCondition() for the same - * condition. - *

- * A rendezvous built on a condition is also provided for synchronizing - * N threads. - */ - - private static HashMap conditions = new HashMap(); - - /* - * Modifiable boolean object - */ - private static class BValue { - boolean v; - } - - /* - * Modifiable int object - */ - private static class IValue { - int v; - IValue (int i) { - v =i; - } - } - - - private static BValue getCond (String condition) { - synchronized (conditions) { - BValue cond = (BValue) conditions.get (condition); - if (cond == null) { - cond = new BValue(); - conditions.put (condition, cond); - } - return cond; - } - } - - /** - * Set the condition to true. Any threads that are currently blocked - * waiting on the condition, will be unblocked and allowed to continue. - * Threads that subsequently call waitForCondition() will not block. - * If the named condition did not exist prior to the call, then it is created - * first. - */ - - public static void setCondition (String condition) { - BValue cond = getCond (condition); - synchronized (cond) { - if (cond.v) { - return; - } - cond.v = true; - cond.notifyAll(); - } - } - - /** - * If the named condition does not exist, then it is created and initialized - * to false. If the condition exists or has just been created and its value - * is false, then the thread blocks until another thread sets the condition. - * If the condition exists and is already set to true, then this call returns - * immediately without blocking. - */ - - public static void waitForCondition (String condition) { - BValue cond = getCond (condition); - synchronized (cond) { - if (!cond.v) { - try { - cond.wait(); - } catch (InterruptedException e) {} - } - } - } - - /* conditions must be locked when accessing this */ - static HashMap rv = new HashMap(); - - /** - * Force N threads to rendezvous (ie. wait for each other) before proceeding. - * The first thread(s) to call are blocked until the last - * thread makes the call. Then all threads continue. - *

- * All threads that call with the same condition name, must use the same value - * for N (or the results may be not be as expected). - *

- * Obviously, if fewer than N threads make the rendezvous then the result - * will be a hang. - */ - - public static void rendezvous (String condition, int N) { - BValue cond; - IValue iv; - String name = "RV_"+condition; - - /* get the condition */ - - synchronized (conditions) { - cond = (BValue)conditions.get (name); - if (cond == null) { - /* we are first caller */ - if (N < 2) { - throw new RuntimeException ("rendezvous must be called with N >= 2"); - } - cond = new BValue (); - conditions.put (name, cond); - iv = new IValue (N-1); - rv.put (name, iv); - } else { - /* already initialised, just decrement the counter */ - iv = (IValue) rv.get (name); - iv.v --; - } - } - - if (iv.v > 0) { - waitForCondition (name); - } else { - setCondition (name); - synchronized (conditions) { - clearCondition (name); - rv.remove (name); - } - } - } - - /** - * If the named condition exists and is set then remove it, so it can - * be re-initialized and used again. If the condition does not exist, or - * exists but is not set, then the call returns without doing anything. - * Note, some higher level synchronization - * may be needed between clear and the other operations. - */ - - public static void clearCondition(String condition) { - BValue cond; - synchronized (conditions) { - cond = (BValue) conditions.get (condition); - if (cond == null) { - return; - } - synchronized (cond) { - if (cond.v) { - conditions.remove (condition); - } - } - } - } -} diff --git a/test/jdk/sun/nio/cs/TestCharsetMapping.java b/test/jdk/sun/nio/cs/TestCharsetMapping.java index 63eeba1774e56009f2e4a811e04990cfc8d296d4..c7bd101aa425a91d69643a859e70982cf87adf7f 100644 --- a/test/jdk/sun/nio/cs/TestCharsetMapping.java +++ b/test/jdk/sun/nio/cs/TestCharsetMapping.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 @@ -569,7 +569,7 @@ public class TestCharsetMapping { public static void main(String args[]) throws Exception { Path dir = Paths.get(System.getProperty("test.src", ".") + - "/../../../../make/data/charsetmapping"); + "/../../../../src/java.base/share/data/charsetmapping"); if (!Files.exists(dir)) { // not inside jdk repo, no mappings, exit silently log.println("Nothing done, not in a jdk repo: "); diff --git a/test/jdk/sun/nio/cs/TestMS950.java b/test/jdk/sun/nio/cs/TestMS950.java index 6d567e077519cd0de790850de8366a2fc10f4f5a..36820f381a04f6efe6052d2d730c9fc59e05ca85 100644 --- a/test/jdk/sun/nio/cs/TestMS950.java +++ b/test/jdk/sun/nio/cs/TestMS950.java @@ -33,7 +33,7 @@ import java.nio.ByteBuffer; import java.util.Arrays; public class TestMS950 { - // Data is listed from make/data/charsetmapping/MS950.map + // Data is listed from src/java.base/share/data/charsetmapping/MS950.map private final static String[] MS950B2C = new String[] { "0xF9FA 0x256D", "0xF9FB 0x256E", diff --git a/test/jdk/sun/security/krb5/auto/HttpsCB.java b/test/jdk/sun/security/krb5/auto/HttpsCB.java index a65aa5d024117be0563b90dbd08022ce7dfe1998..1f9f0de33aca6ddf9bf44a27f915375672a0c288 100644 --- a/test/jdk/sun/security/krb5/auto/HttpsCB.java +++ b/test/jdk/sun/security/krb5/auto/HttpsCB.java @@ -23,7 +23,7 @@ /* * @test - * @bug 8279842 + * @bug 8279842 8282293 * @modules java.base/sun.security.util * java.security.jgss/sun.security.jgss * java.security.jgss/sun.security.jgss.krb5 @@ -52,7 +52,13 @@ * @run main/othervm -Djdk.net.hosts.file=TestHosts * -Djdk.https.negotiate.cbt=domain:host.web.domain HttpsCB true true * @run main/othervm -Djdk.net.hosts.file=TestHosts + * -Djdk.https.negotiate.cbt=domain:HOST.WEB.DOMAIN HttpsCB true true + * @run main/othervm -Djdk.net.hosts.file=TestHosts * -Djdk.https.negotiate.cbt=domain:*.web.domain HttpsCB true true + * @run main/othervm -Djdk.net.hosts.file=TestHosts + * -Djdk.https.negotiate.cbt=domain:*.WEB.Domain HttpsCB true true + * @run main/othervm -Djdk.net.hosts.file=TestHosts + * -Djdk.https.negotiate.cbt=domain:*.Invalid,*.WEB.Domain HttpsCB true true */ import com.sun.net.httpserver.Headers; @@ -198,6 +204,7 @@ public class HttpsCB { conn.getInputStream())); return reader.readLine().equals(CONTENT); } catch (IOException e) { + e.printStackTrace(System.out); return false; } } diff --git a/test/jdk/sun/security/lib/CheckBlockedCerts.java b/test/jdk/sun/security/lib/CheckBlockedCerts.java index e5561bf15b82898721fde7f637473e7b723a6d99..5afbf4b610b9f58cb9f52422e1e1d3280a933391 100644 --- a/test/jdk/sun/security/lib/CheckBlockedCerts.java +++ b/test/jdk/sun/security/lib/CheckBlockedCerts.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 @@ -61,7 +61,7 @@ public class CheckBlockedCerts { // Assumes the full src is available File blockedCertsFile = new File(System.getProperty("test.src"), - "../../../../../make/data/blockedcertsconverter/blocked.certs.pem"); + "../../../../../src/java.base/share/data/blockedcertsconverter/blocked.certs.pem"); CertificateFactory cf = CertificateFactory.getInstance("X.509"); try (FileInputStream fis = new FileInputStream(blockedCertsFile)) { diff --git a/test/jdk/sun/security/lib/cacerts/VerifyCACerts.java b/test/jdk/sun/security/lib/cacerts/VerifyCACerts.java index 884384f2999f57e0e6053f67cbc7890c5f4a968b..00abee8919181623320063ef87f3fd3564421781 100644 --- a/test/jdk/sun/security/lib/cacerts/VerifyCACerts.java +++ b/test/jdk/sun/security/lib/cacerts/VerifyCACerts.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 @@ -264,6 +264,8 @@ public class VerifyCACerts { add("luxtrustglobalrootca [jdk]"); // Valid until: Wed Mar 17 11:33:33 PDT 2021 add("quovadisrootca [jdk]"); + // Valid until: Sat May 21 04:00:00 GMT 2022 + add("geotrustglobalca [jdk]"); } }; diff --git a/test/jdk/sun/security/provider/certpath/DisabledAlgorithms/CPBuilder.java b/test/jdk/sun/security/provider/certpath/DisabledAlgorithms/CPBuilder.java index 3edf02d70d7caa1412201b8ec007a6c8f1cdba49..0037ac7bad64f95b78e4451195820c05d003424e 100644 --- a/test/jdk/sun/security/provider/certpath/DisabledAlgorithms/CPBuilder.java +++ b/test/jdk/sun/security/provider/certpath/DisabledAlgorithms/CPBuilder.java @@ -348,7 +348,7 @@ public class CPBuilder { for (String key : certmap.keySet()) { String certStr = certmap.get(key); ByteArrayInputStream is = - new ByteArrayInputStream(certStr.getBytes());; + new ByteArrayInputStream(certStr.getBytes()); Certificate cert = cf.generateCertificate(is); entries.add(cert); } diff --git a/test/jdk/sun/security/provider/certpath/DisabledAlgorithms/CPBuilderWithMD5.java b/test/jdk/sun/security/provider/certpath/DisabledAlgorithms/CPBuilderWithMD5.java index e6a9765037bc9aa851b4186dbb636c219fce7914..9785b2702998e9ebb7b4ed18a9a3973ce3d879a2 100644 --- a/test/jdk/sun/security/provider/certpath/DisabledAlgorithms/CPBuilderWithMD5.java +++ b/test/jdk/sun/security/provider/certpath/DisabledAlgorithms/CPBuilderWithMD5.java @@ -353,7 +353,7 @@ public class CPBuilderWithMD5 { for (String key : certmap.keySet()) { String certStr = certmap.get(key); ByteArrayInputStream is = - new ByteArrayInputStream(certStr.getBytes());; + new ByteArrayInputStream(certStr.getBytes()); Certificate cert = cf.generateCertificate(is); entries.add(cert); } diff --git a/test/jdk/sun/security/ssl/CipherSuite/NoDesRC4CiphSuite.java b/test/jdk/sun/security/ssl/CipherSuite/NoDesRC4DesEdeCiphSuite.java similarity index 92% rename from test/jdk/sun/security/ssl/CipherSuite/NoDesRC4CiphSuite.java rename to test/jdk/sun/security/ssl/CipherSuite/NoDesRC4DesEdeCiphSuite.java index 22238d38e1d5ff05b20e8b5e9b463f258daa7760..c9861324237c16e333b9ce912d79a7ddf6ee3359 100644 --- a/test/jdk/sun/security/ssl/CipherSuite/NoDesRC4CiphSuite.java +++ b/test/jdk/sun/security/ssl/CipherSuite/NoDesRC4DesEdeCiphSuite.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,9 +23,9 @@ /* * @test - * @bug 8208350 - * @summary Disable all DES cipher suites - * @run main/othervm NoDesRC4CiphSuite + * @bug 8208350 8163327 + * @summary Disable all DES, RC4, and 3DES/DesEde cipher suites + * @run main/othervm NoDesRC4DesEdeCiphSuite */ /* @@ -43,7 +43,7 @@ import java.util.List; import java.util.ArrayList; import java.util.Arrays; -public class NoDesRC4CiphSuite { +public class NoDesRC4DesEdeCiphSuite { private static final boolean DEBUG = false; @@ -80,6 +80,18 @@ public class NoDesRC4CiphSuite { "SSL_RSA_EXPORT_WITH_RC4_40_MD5", "SSL_DH_anon_EXPORT_WITH_RC4_40_MD5" }; + private static final List DESEDE_CS_LIST = Arrays.asList( + 0xC008, 0xC012, 0x0016, 0x0013, 0xC003, 0xC00D, 0x000A + ); + private static final String[] DESEDE_CS_LIST_NAMES = new String[] { + "TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA", + "TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA", + "SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA", + "SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA", + "TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA", + "TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA", + "SSL_RSA_WITH_3DES_EDE_CBC_SHA" + }; private static final ByteBuffer CLIOUTBUF = ByteBuffer.wrap("Client Side".getBytes()); @@ -99,6 +111,11 @@ public class NoDesRC4CiphSuite { allGood &= testEngAddDisabled(RC4_CS_LIST_NAMES, RC4_CS_LIST); allGood &= testEngOnlyDisabled(RC4_CS_LIST_NAMES); + // Disabled 3DES tests + allGood &= testDefaultCase(DESEDE_CS_LIST); + allGood &= testEngAddDisabled(DESEDE_CS_LIST_NAMES, DESEDE_CS_LIST); + allGood &= testEngOnlyDisabled(DESEDE_CS_LIST_NAMES); + if (allGood) { System.err.println("All tests passed"); } else { diff --git a/test/jdk/sun/security/ssl/InputRecord/ClientHelloRead.java b/test/jdk/sun/security/ssl/InputRecord/ClientHelloRead.java index e08230f325d59fcaa2554119548569ba214e20c3..06cba1091396954204ac1c2391fa7dd48acbef2f 100644 --- a/test/jdk/sun/security/ssl/InputRecord/ClientHelloRead.java +++ b/test/jdk/sun/security/ssl/InputRecord/ClientHelloRead.java @@ -32,12 +32,22 @@ * system properties in samevm/agentvm mode. */ -import java.io.*; -import java.net.*; +import java.io.BufferedReader; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStreamReader; +import java.net.ServerSocket; +import java.net.URL; import java.security.KeyStore; -import javax.net.*; -import javax.net.ssl.*; -import java.security.cert.*; + +import javax.net.ServerSocketFactory; +import javax.net.ssl.HostnameVerifier; +import javax.net.ssl.HttpsURLConnection; +import javax.net.ssl.KeyManagerFactory; +import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLException; +import javax.net.ssl.SSLServerSocketFactory; +import javax.net.ssl.SSLSession; /* * ClientHelloRead.java -- includes a simple server that can serve diff --git a/test/jdk/sun/security/tools/jarsigner/AutoKeyStore.java b/test/jdk/sun/security/tools/jarsigner/AutoKeyStore.java new file mode 100644 index 0000000000000000000000000000000000000000..971d9599b6c783b39b0aea07e4e6a78287b37361 --- /dev/null +++ b/test/jdk/sun/security/tools/jarsigner/AutoKeyStore.java @@ -0,0 +1,190 @@ +/* + * 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 8281234 + * @summary The -protected option is not always checked in keytool and jarsigner + * @library /test/lib + * @modules java.base/sun.security.tools.keytool + * java.base/sun.security.x509 + */ + +import jdk.test.lib.Asserts; +import jdk.test.lib.SecurityTools; +import jdk.test.lib.util.JarUtils; +import sun.security.tools.keytool.CertAndKeyGen; +import sun.security.x509.X500Name; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.nio.file.Files; +import java.nio.file.Path; +import java.security.*; +import java.security.cert.Certificate; +import java.security.cert.X509Certificate; +import java.util.Collections; +import java.util.Date; +import java.util.Enumeration; +import java.util.List; +import java.util.jar.JarFile; + +public class AutoKeyStore { + + public static void main(String[] args) throws Exception { + + JarUtils.createJarFile(Path.of("unsigned.jar"), Path.of("."), + Files.writeString(Path.of("file"), "hello")); + + SecurityTools.keytool(""" + -J--add-exports -Jjava.base/sun.security.tools.keytool=ALL-UNNAMED + -J--add-exports -Jjava.base/sun.security.x509=ALL-UNNAMED + -providerClass AutoKeyStore$AutoProvider + -providerPath $test.classes + -storetype AUTO -keystore NONE -protected + -list + """).shouldHaveExitValue(0) + .shouldContain("Keystore type: AUTO") + .shouldContain("Keystore provider: AUTO") + .shouldContain("PrivateKeyEntry"); + + SecurityTools.jarsigner(""" + -J--add-exports -Jjava.base/sun.security.tools.keytool=ALL-UNNAMED + -J--add-exports -Jjava.base/sun.security.x509=ALL-UNNAMED + -providerClass AutoKeyStore$AutoProvider + -providerPath $test.classes + -storetype AUTO -keystore NONE -protected + -signedJar signed.jar + unsigned.jar + one + """).shouldHaveExitValue(0) + .shouldContain("jar signed."); + + Asserts.assertTrue(new JarFile("signed.jar") + .getEntry("META-INF/ONE.EC") != null); + } + + public static class AutoProvider extends Provider { + public AutoProvider() { + super("AUTO", "1.1.1", "auto"); + put("KeyStore.AUTO", "AutoKeyStore$KeyStoreImpl"); + } + } + + // This keystore is not based on file. Whenever it's loaded + // a self-sign certificate is generated inside + public static class KeyStoreImpl extends KeyStoreSpi { + + private PrivateKey pri; + private PublicKey pub; + private X509Certificate cert; + + @Override + public Key engineGetKey(String alias, char[] password) { + return pri; + } + + @Override + public Certificate[] engineGetCertificateChain(String alias) { + return new Certificate[] { cert }; + } + + @Override + public Certificate engineGetCertificate(String alias) { + return cert; + } + + @Override + public Date engineGetCreationDate(String alias) { + return new Date(); + } + + @Override + public void engineSetKeyEntry(String alias, Key key, char[] password, Certificate[] chain) throws KeyStoreException { + throw new KeyStoreException("Not supported"); + } + + @Override + public void engineSetKeyEntry(String alias, byte[] key, Certificate[] chain) throws KeyStoreException { + throw new KeyStoreException("Not supported"); + } + + @Override + public void engineSetCertificateEntry(String alias, Certificate cert) throws KeyStoreException { + throw new KeyStoreException("Not supported"); + } + + @Override + public void engineDeleteEntry(String alias) throws KeyStoreException { + throw new KeyStoreException("Not supported"); + } + + @Override + public Enumeration engineAliases() { + return Collections.enumeration(List.of("one")); + } + + @Override + public boolean engineContainsAlias(String alias) { + return alias.equalsIgnoreCase("one"); + } + + @Override + public int engineSize() { + return 1; + } + + @Override + public boolean engineIsKeyEntry(String alias) { + return true; + } + + @Override + public boolean engineIsCertificateEntry(String alias) { + return false; + } + + @Override + public String engineGetCertificateAlias(Certificate cert) { + return "one"; + } + + @Override + public void engineStore(OutputStream stream, char[] password) { + } + + @Override + public void engineLoad(InputStream stream, char[] password) throws IOException { + try { + CertAndKeyGen cag = new CertAndKeyGen("EC", "SHA256withECDSA"); + cag.generate("secp256r1"); + pri = cag.getPrivateKey(); + pub = cag.getPublicKey(); + cert = cag.getSelfCertificate(new X500Name("CN=one"), 3600); + } catch (Exception e) { + throw new IOException("Not loaded"); + } + } + } +} diff --git a/test/jdk/sun/security/tools/jarsigner/CheckAlgParams.java b/test/jdk/sun/security/tools/jarsigner/CheckAlgParams.java new file mode 100644 index 0000000000000000000000000000000000000000..d0a4338fee3b2d1f0299f21ce9c13725403251db --- /dev/null +++ b/test/jdk/sun/security/tools/jarsigner/CheckAlgParams.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. + */ + +/* + * @test + * @bug 8277474 + * @summary jarsigner -verify should check if the algorithm parameters of + * its signature algorithm use disabled or legacy algorithms + * @library /test/lib + */ + +import jdk.test.lib.SecurityTools; +import jdk.test.lib.process.OutputAnalyzer; +import jdk.test.lib.util.JarUtils; + +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; + +public class CheckAlgParams { + private static final String JAVA_SECURITY_FILE = "java.security"; + + public static void main(String[] args) throws Exception{ + + SecurityTools.keytool("-keystore ks -storepass changeit " + + "-genkeypair -keyalg RSASSA-PSS -alias ca -dname CN=CA " + + "-ext bc:c") + .shouldHaveExitValue(0); + + JarUtils.createJarFile(Path.of("a.jar"), Path.of("."), Path.of("ks")); + + SecurityTools.jarsigner("-keystore ks -storepass changeit " + + "-signedjar signeda.jar " + + "-verbose" + + " a.jar ca") + .shouldHaveExitValue(0); + + Files.writeString(Files.createFile(Paths.get(JAVA_SECURITY_FILE)), + "jdk.jar.disabledAlgorithms=SHA256\n" + + "jdk.security.legacyAlgorithms=\n"); + + SecurityTools.jarsigner("-verify signeda.jar " + + "-J-Djava.security.properties=" + + JAVA_SECURITY_FILE + + " -keystore ks -storepass changeit -verbose -debug") + .shouldMatch("Digest algorithm: SHA-256.*(disabled)") + .shouldMatch("Signature algorithm: RSASSA-PSS using PSSParameterSpec.*hashAlgorithm=SHA-256.*(disabled)") + .shouldContain("The jar will be treated as unsigned") + .shouldHaveExitValue(0); + + Files.deleteIfExists(Paths.get(JAVA_SECURITY_FILE)); + Files.writeString(Files.createFile(Paths.get(JAVA_SECURITY_FILE)), + "jdk.jar.disabledAlgorithms=\n" + + "jdk.security.legacyAlgorithms=SHA256\n"); + + SecurityTools.jarsigner("-verify signeda.jar " + + "-J-Djava.security.properties=" + + JAVA_SECURITY_FILE + + " -keystore ks -storepass changeit -verbose -debug") + .shouldMatch("Digest algorithm: SHA-256.*(weak)") + .shouldMatch("Signature algorithm: RSASSA-PSS using PSSParameterSpec.*hashAlgorithm=SHA-256.*(weak)") + .shouldNotContain("The jar will be treated as unsigned") + .shouldHaveExitValue(0); + } +} diff --git a/test/jdk/sun/security/tools/jarsigner/DisableCurveTest.java b/test/jdk/sun/security/tools/jarsigner/DisableCurveTest.java new file mode 100644 index 0000000000000000000000000000000000000000..9270899182c8702b04ef78d4e3d7486144c09f8f --- /dev/null +++ b/test/jdk/sun/security/tools/jarsigner/DisableCurveTest.java @@ -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. + */ + +/* + * @test + * @bug 8282633 + * @summary jarsigner should display the named curve to better explain why + * an EC key is disabled or will be disabled. + * @library /test/lib + */ + +import jdk.test.lib.SecurityTools; +import jdk.test.lib.process.OutputAnalyzer; +import jdk.test.lib.util.JarUtils; + +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; + +public class DisableCurveTest { + private static final String JAVA_SECURITY_FILE = "java.security"; + + public static void main(String[] args) throws Exception{ + SecurityTools.keytool("-keystore ks -storepass changeit " + + "-genkeypair -keyalg EC -alias ca -dname CN=CA " + + "-ext bc:c") + .shouldHaveExitValue(0); + + JarUtils.createJarFile(Path.of("a.jar"), Path.of("."), Path.of("ks")); + + Files.writeString(Files.createFile(Paths.get(JAVA_SECURITY_FILE)), + "jdk.jar.disabledAlgorithms=secp256r1\n" + + "jdk.certpath.disabledAlgorithms=secp256r1\n"); + + SecurityTools.jarsigner("-keystore ks -storepass changeit " + + "-signedjar signeda.jar -verbose " + + "-J-Djava.security.properties=" + + JAVA_SECURITY_FILE + + " a.jar ca") + .shouldContain(">>> Signer") + .shouldContain("Signature algorithm: SHA256withECDSA, 256-bit EC (secp256r1) key (disabled)") + .shouldContain("Warning:") + .shouldContain("The EC (secp256r1) signing key has a keysize of 256 which is considered a security risk and is disabled") + .shouldHaveExitValue(0); + + SecurityTools.jarsigner("-verify signeda.jar " + + "-J-Djava.security.properties=" + + JAVA_SECURITY_FILE + + " -keystore ks -storepass changeit -verbose -debug") + .shouldContain("- Signed by") + .shouldContain("Signature algorithm: SHA256withECDSA, 256-bit EC (secp256r1) key (disabled)") + .shouldContain("WARNING: The jar will be treated as unsigned") + .shouldHaveExitValue(0); + + Files.deleteIfExists(Paths.get(JAVA_SECURITY_FILE)); + Files.writeString(Files.createFile(Paths.get(JAVA_SECURITY_FILE)), + "jdk.security.legacyAlgorithms=secp256r1\n"); + + SecurityTools.jarsigner("-keystore ks -storepass changeit " + + "-signedjar signeda.jar -verbose " + + "-J-Djava.security.properties=" + + JAVA_SECURITY_FILE + + " a.jar ca") + .shouldContain(">>> Signer") + .shouldContain("Signature algorithm: SHA256withECDSA, 256-bit EC (secp256r1) key (weak)") + .shouldContain("Warning:") + .shouldContain("The EC (secp256r1) signing key has a keysize of 256 which is considered a security risk. This key size will be disabled in a future update") + .shouldHaveExitValue(0); + + SecurityTools.jarsigner("-verify signeda.jar " + + "-J-Djava.security.properties=" + + JAVA_SECURITY_FILE + + " -keystore ks -storepass changeit -verbose -debug") + .shouldContain("- Signed by") + .shouldContain("Signature algorithm: SHA256withECDSA, 256-bit EC (secp256r1) key (weak)") + .shouldContain("jar verified") + .shouldContain("The EC (secp256r1) signing key has a keysize of 256 which is considered a security risk. This key size will be disabled in a future update") + .shouldHaveExitValue(0); + } +} diff --git a/test/jdk/sun/security/util/HostnameMatcher/NullHostnameCheck.java b/test/jdk/sun/security/util/HostnameChecker/NullHostnameCheck.java similarity index 100% rename from test/jdk/sun/security/util/HostnameMatcher/NullHostnameCheck.java rename to test/jdk/sun/security/util/HostnameChecker/NullHostnameCheck.java diff --git a/test/jdk/sun/security/util/HostnameMatcher/TestHostnameChecker.java b/test/jdk/sun/security/util/HostnameChecker/TestHostnameChecker.java similarity index 88% rename from test/jdk/sun/security/util/HostnameMatcher/TestHostnameChecker.java rename to test/jdk/sun/security/util/HostnameChecker/TestHostnameChecker.java index 8d50aa4c29592651755927ddd31a6655f892bbf3..d5c0898d8e658db20936855c1cf390dfffadbf1d 100644 --- a/test/jdk/sun/security/util/HostnameMatcher/TestHostnameChecker.java +++ b/test/jdk/sun/security/util/HostnameChecker/TestHostnameChecker.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 @@ -23,16 +23,19 @@ /* * @test - * @bug 4514108 - * @summary Verify host name matching behaves as defined in RFC2818. + * @bug 4514108 7192189 + * @summary Verify host name matching behaves as defined in RFC2818 and RFC6125. * @library /test/lib - * @modules java.base/sun.security.util + * @modules java.base/sun.security.util java.base/sun.security.x509 */ import java.security.cert.*; +import java.util.Collection; +import java.util.List; import jdk.test.lib.security.CertUtils; import sun.security.util.*; +import sun.security.x509.X509CertImpl; /** * Certificate 1: @@ -193,10 +196,17 @@ public class TestHostnameChecker { check(checker, "altfoo2.com", cert3, true); check(checker, "5.6.7.8", cert3, true); check(checker, "foo.bar.com", cert4, true); - check(checker, "altfoo.bar.com", cert4, true); + check(checker, "altfoo.bar.com", cert4, false); check(checker, "2001:db8:3c4d:15::1a2f:1a2b", cert5, true); check(checker, "2001:0db8:3c4d:0015:0000:0000:1a2f:1a2b", cert5, true); check(checker, "2002:db8:3c4d:15::1a2f:1a2b", cert5, false); + check(checker, "foo.bar.example.net", mock("foo.*.example.net"), false); + check(checker, "baz1.example.net", mock("baz*.example.net"), true); + check(checker, "foobaz.example.net", mock("*baz.example.net"), true); + check(checker, "buzz.example.net", mock("b*z.example.net"), true); + check(checker, "公司.example.net", mock("xn--5*.example.net"), false); + check(checker, "公司.江利子.example.net", + mock("*.xn--kcry6tjko.example.net"), true); checker = HostnameChecker.getInstance( HostnameChecker.TYPE_LDAP); @@ -214,6 +224,15 @@ public class TestHostnameChecker { check(checker, "altfoo.bar.com", cert4, false); } + private static X509Certificate mock(String domain) { + return new X509CertImpl() { + @Override + public Collection> getSubjectAlternativeNames() { + return List.of(List.of(2, domain)); + } + }; + } + private static void check(HostnameChecker checker, String name, X509Certificate cert, boolean expectedResult) throws Exception { @@ -224,7 +243,7 @@ public class TestHostnameChecker { } } catch (CertificateException e) { if (expectedResult == true) { - throw e; + throw new Exception("Failed valid test: " + name, e); } } System.out.println("OK: " + name); diff --git a/test/jdk/sun/security/util/HostnameMatcher/cert1.crt b/test/jdk/sun/security/util/HostnameChecker/cert1.crt similarity index 100% rename from test/jdk/sun/security/util/HostnameMatcher/cert1.crt rename to test/jdk/sun/security/util/HostnameChecker/cert1.crt diff --git a/test/jdk/sun/security/util/HostnameMatcher/cert2.crt b/test/jdk/sun/security/util/HostnameChecker/cert2.crt similarity index 100% rename from test/jdk/sun/security/util/HostnameMatcher/cert2.crt rename to test/jdk/sun/security/util/HostnameChecker/cert2.crt diff --git a/test/jdk/sun/security/util/HostnameMatcher/cert3.crt b/test/jdk/sun/security/util/HostnameChecker/cert3.crt similarity index 100% rename from test/jdk/sun/security/util/HostnameMatcher/cert3.crt rename to test/jdk/sun/security/util/HostnameChecker/cert3.crt diff --git a/test/jdk/sun/security/util/HostnameMatcher/cert4.crt b/test/jdk/sun/security/util/HostnameChecker/cert4.crt similarity index 100% rename from test/jdk/sun/security/util/HostnameMatcher/cert4.crt rename to test/jdk/sun/security/util/HostnameChecker/cert4.crt diff --git a/test/jdk/sun/security/util/HostnameMatcher/cert5.crt b/test/jdk/sun/security/util/HostnameChecker/cert5.crt similarity index 100% rename from test/jdk/sun/security/util/HostnameMatcher/cert5.crt rename to test/jdk/sun/security/util/HostnameChecker/cert5.crt diff --git a/test/jdk/sun/security/util/Pem/encoding.sh b/test/jdk/sun/security/util/Pem/encoding.sh index 2bc39504218e81e884af8f8ac07feec565a9193d..7f8b142caf898d8b2f11b440c477c66f70f6a85e 100644 --- a/test/jdk/sun/security/util/Pem/encoding.sh +++ b/test/jdk/sun/security/util/Pem/encoding.sh @@ -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 @@ -32,4 +32,4 @@ $TESTJAVA/bin/java $TESTVMOPTS -cp $TESTCLASSES \ -Dfile.encoding=UTF-16 \ - PemEncoding $TESTSRC/../HostnameMatcher/cert5.crt + PemEncoding $TESTSRC/../HostnameChecker/cert5.crt diff --git a/test/jdk/sun/security/util/RegisteredDomain/ParseNames.java b/test/jdk/sun/security/util/RegisteredDomain/ParseNames.java index 7b9433bbac9992bf91f9d57091e658c80ae2a481..69ca9577c687f4b89d6acb4f16a52d50716e391c 100644 --- a/test/jdk/sun/security/util/RegisteredDomain/ParseNames.java +++ b/test/jdk/sun/security/util/RegisteredDomain/ParseNames.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 @@ -23,7 +23,7 @@ /* * @test - * @bug 8228969 8244087 + * @bug 8228969 8244087 8255266 * @modules java.base/sun.security.util * @summary unit test for RegisteredDomain */ diff --git a/test/jdk/sun/security/util/RegisteredDomain/tests.dat b/test/jdk/sun/security/util/RegisteredDomain/tests.dat index da9fba064fb34d75bf6297dbb83c340db00e95b0..e4cf659c6341a0df41390888a78d8a73a3e44b17 100644 --- a/test/jdk/sun/security/util/RegisteredDomain/tests.dat +++ b/test/jdk/sun/security/util/RegisteredDomain/tests.dat @@ -56,6 +56,11 @@ biz biz null site.biz biz site.biz w.site.biz biz site.biz +# br +br br null +dev.br dev.br null +x.dev.br dev.br x.dev.br + # cn (unicode) # foo.mil.cn mil.cn foo.mil.cn diff --git a/test/jdk/sun/security/x509/OtherName/Parse.java b/test/jdk/sun/security/x509/OtherName/Parse.java new file mode 100644 index 0000000000000000000000000000000000000000..7db5ffe56d262126843db076447b263e3a2b3b71 --- /dev/null +++ b/test/jdk/sun/security/x509/OtherName/Parse.java @@ -0,0 +1,102 @@ +/* + * 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 8277976 + * @summary Break up SEQUENCE in X509Certificate::getSubjectAlternativeNames + * and X509Certificate::getIssuerAlternativeNames in otherName + * @modules java.base/sun.security.util + * java.base/sun.security.x509 + * java.base/sun.security.tools.keytool + * @library /test/lib + */ + +import jdk.test.lib.Asserts; +import sun.security.tools.keytool.CertAndKeyGen; +import sun.security.util.DerValue; +import sun.security.util.ObjectIdentifier; +import sun.security.x509.CertificateExtensions; +import sun.security.x509.DNSName; +import sun.security.x509.GeneralName; +import sun.security.x509.GeneralNames; +import sun.security.x509.OIDMap; +import sun.security.x509.OtherName; +import sun.security.x509.SubjectAlternativeNameExtension; +import sun.security.x509.X500Name; + +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.security.cert.X509Certificate; +import java.util.Arrays; +import java.util.Date; + +public class Parse { + + public static class MyDNSName extends DNSName { + public MyDNSName(byte[] in) throws IOException { + super(new String(Arrays.copyOfRange(in, 2, in.length), + StandardCharsets.US_ASCII)); + } + } + + public static void main(String[] args) throws Exception { + OIDMap.addAttribute("n1", "1.2.3.6", MyDNSName.class); + + CertificateExtensions exts = new CertificateExtensions(); + GeneralNames names = new GeneralNames(); + + byte[] d1 = new byte[] { + DerValue.tag_OctetString, 5, 'a', '.', 'c', 'o', 'm' }; + names.add(new GeneralName( + new OtherName(ObjectIdentifier.of("1.2.3.5"), d1))); + + byte[] d2 = new byte[] { + DerValue.tag_UTF8String, 5, 'a', '.', 'c', 'o', 'm' }; + names.add(new GeneralName( + new OtherName(ObjectIdentifier.of("1.2.3.6"), d2))); + + exts.set("x", new SubjectAlternativeNameExtension(names)); + CertAndKeyGen g = new CertAndKeyGen("Ed25519", "Ed25519"); + g.generate(-1); + X509Certificate x = g.getSelfCertificate(new X500Name("CN=ME"), + new Date(), + 100000, + exts); + + int found = 0; + for (var san : x.getSubjectAlternativeNames()) { + if (san.size() >= 4 && san.get(0).equals(0)) { + if (san.get(2).equals("1.2.3.5")) { + Asserts.assertTrue(Arrays.equals((byte[]) san.get(3), d1)); + found++; + } else if (san.get(2).equals("1.2.3.6")) { + Asserts.assertEQ(san.get(3), "a.com"); + found++; + } + } + } + Asserts.assertEQ(found, 2); + } +} + diff --git a/test/jdk/sun/text/resources/LocaleData b/test/jdk/sun/text/resources/LocaleData index ba1760978251d0e3a9fc17a9782eb8e3a6f5eff2..50fa417ae6d188dbea4ca5815fbb080a6d134f97 100644 --- a/test/jdk/sun/text/resources/LocaleData +++ b/test/jdk/sun/text/resources/LocaleData @@ -6448,6 +6448,7 @@ CurrencyNames//rsd=Serbian Dinar CurrencyNames//scr=Seychellois Rupee CurrencyNames//sdd=Sudanese Dinar (1992-2007) CurrencyNames//sit=Slovenian Tolar +CurrencyNames//sle=Sierra Leonean Leone CurrencyNames//sll=Sierra Leonean Leone CurrencyNames//srd=Surinamese Dollar CurrencyNames//srg=Surinamese Guilder diff --git a/test/jdk/sun/text/resources/LocaleDataTest.java b/test/jdk/sun/text/resources/LocaleDataTest.java index 5b812f67ff583b221d54a05a3dcffa6da615680d..4c617e2381d894815538cf426478d8d11da148fb 100644 --- a/test/jdk/sun/text/resources/LocaleDataTest.java +++ b/test/jdk/sun/text/resources/LocaleDataTest.java @@ -40,7 +40,7 @@ * 8145136 8145952 8164784 8037111 8081643 7037368 8178872 8185841 8190918 * 8187946 8195478 8181157 8179071 8193552 8202026 8204269 8202537 8208746 * 8209775 8221432 8227127 8230284 8231273 8233579 8234288 8250665 8255086 - * 8251317 8265315 8274658 + * 8251317 8274658 8283277 8274658 * @summary Verify locale data * @modules java.base/sun.util.resources * @modules jdk.localedata diff --git a/test/jdk/sun/tools/jhsdb/BasicLauncherTest.java b/test/jdk/sun/tools/jhsdb/BasicLauncherTest.java index 401dfe6ca312e8f29c7f7d7553fe32235046cb56..d2ca78f044ac43920e6813dd6e684647f2ca3174 100644 --- a/test/jdk/sun/tools/jhsdb/BasicLauncherTest.java +++ b/test/jdk/sun/tools/jhsdb/BasicLauncherTest.java @@ -134,7 +134,7 @@ public class BasicLauncherTest { launcher.addToolArg("--pid=" + Long.toString(theApp.getPid())); ProcessBuilder processBuilder = SATestUtils.createProcessBuilder(launcher); - OutputAnalyzer output = ProcessTools.executeProcess(processBuilder);; + OutputAnalyzer output = ProcessTools.executeProcess(processBuilder); output.shouldContain("No deadlocks found"); output.shouldNotContain("illegal bci"); output.shouldNotContain("AssertionFailure"); @@ -171,7 +171,7 @@ public class BasicLauncherTest { ProcessBuilder processBuilder = SATestUtils.createProcessBuilder(launcher); processBuilder.redirectError(ProcessBuilder.Redirect.INHERIT); - OutputAnalyzer output = ProcessTools.executeProcess(processBuilder);; + OutputAnalyzer output = ProcessTools.executeProcess(processBuilder); output.shouldContain(expectedMessage); unexpectedMessage.ifPresent(output::shouldNotContain); output.shouldHaveExitValue(0); diff --git a/test/jdk/sun/util/calendar/zi/TestZoneInfo310.java b/test/jdk/sun/util/calendar/zi/TestZoneInfo310.java index 7b50c342a0d3c1943ca5b57b9495dbdd55db13a1..ef6405860f5b1c534789acf43e6fe2206844b3ae 100644 --- a/test/jdk/sun/util/calendar/zi/TestZoneInfo310.java +++ b/test/jdk/sun/util/calendar/zi/TestZoneInfo310.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 @@ -47,7 +47,7 @@ public class TestZoneInfo310 { String TESTDIR = System.getProperty("test.dir", "."); Path tzdir = Paths.get(System.getProperty("test.root"), - "..", "..", "make", "data", "tzdata"); + "../../src/java.base/share/data/tzdata"); String tzfiles = "africa antarctica asia australasia europe northamerica southamerica backward etcetera gmt"; Path jdk_tzdir = Paths.get(System.getProperty("test.src"), "tzdata_jdk"); String jdk_tzfiles = "jdk11_backward"; diff --git a/test/jdk/tools/jar/modularJar/Basic.java b/test/jdk/tools/jar/modularJar/Basic.java index 26e9b835a496d1d38a50bfcf54ab4fce17f00c7b..177ae2a84534d5476f380ef1d1d927c1de6df6c6 100644 --- a/test/jdk/tools/jar/modularJar/Basic.java +++ b/test/jdk/tools/jar/modularJar/Basic.java @@ -123,7 +123,7 @@ public class Basic { moduleName = mn; mainClass = mc; version = v; message = m; hashes = h; this.requires = requires != null ? requires : Collections.emptySet(); this.exports = exports != null ? exports : Collections.emptySet(); - this.uses = uses != null ? uses : Collections.emptySet();; + this.uses = uses != null ? uses : Collections.emptySet(); this.provides = provides != null ? provides : Collections.emptySet(); this.packages = Stream.concat(this.exports.stream(), contains.stream()) .collect(Collectors.toSet()); diff --git a/test/jdk/tools/jar/multiRelease/data/test13/v10/version/Nested.java b/test/jdk/tools/jar/multiRelease/data/test13/v10/version/Nested.java index 7acd05676b446ac2a309a0b292709f204ca6343b..35f43edcb392077ebb910c7a21430cbfe5046eb5 100644 --- a/test/jdk/tools/jar/multiRelease/data/test13/v10/version/Nested.java +++ b/test/jdk/tools/jar/multiRelease/data/test13/v10/version/Nested.java @@ -12,7 +12,7 @@ public class Nested { int save = getVersion(); class nestnested { - int save = getVersion();; + int save = getVersion(); } } } diff --git a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/AdditionalLauncher.java b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/AdditionalLauncher.java index 44d75d98ec9c35cffd2b578867ba9a5e39fc5c3f..8c6bbc1fa4314c3228948495965b842fea33cd2d 100644 --- a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/AdditionalLauncher.java +++ b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/AdditionalLauncher.java @@ -32,6 +32,7 @@ import java.util.Map; import java.util.Objects; import java.util.Optional; import java.util.function.BiConsumer; +import java.util.function.Supplier; import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.stream.Collectors; @@ -86,6 +87,18 @@ public class AdditionalLauncher { return this; } + final public String getRawPropertyValue( + String key, Supplier getDefault) { + return rawProperties.stream() + .filter(item -> item.getKey().equals(key)) + .map(e -> e.getValue()).findAny().orElseGet(getDefault); + } + + private String getDesciption(JPackageCommand cmd) { + return getRawPropertyValue("description", () -> cmd.getArgumentValue( + "--description", unused -> cmd.name())); + } + final public AdditionalLauncher setShortcuts(boolean menu, boolean shortcut) { withMenuShortcut = menu; withShortcut = shortcut; @@ -281,9 +294,30 @@ public class AdditionalLauncher { } } + private void verifyDescription(JPackageCommand cmd) throws IOException { + if (TKit.isWindows()) { + String expectedDescription = getDesciption(cmd); + Path launcherPath = cmd.appLauncherPath(name); + String actualDescription = + WindowsHelper.getExecutableDesciption(launcherPath); + TKit.assertEquals(expectedDescription, actualDescription, + String.format("Check file description of [%s]", launcherPath)); + } else if (TKit.isLinux() && !cmd.isImagePackageType()) { + String expectedDescription = getDesciption(cmd); + Path desktopFile = LinuxHelper.getDesktopFile(cmd, name); + if (Files.exists(desktopFile)) { + TKit.assertTextStream("Comment=" + expectedDescription) + .label(String.format("[%s] file", desktopFile)) + .predicate(String::equals) + .apply(Files.readAllLines(desktopFile).stream()); + } + } + } + protected void verify(JPackageCommand cmd) throws IOException { verifyIcon(cmd); verifyShortcuts(cmd); + verifyDescription(cmd); Path launcherPath = cmd.appLauncherPath(name); diff --git a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/WindowsHelper.java b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/WindowsHelper.java index a3f67e01d460195cccfd608b75169ab3ecf19ae8..d8bbdf113bce864747a9a02c27ce71e54ea55dfd 100644 --- a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/WindowsHelper.java +++ b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/WindowsHelper.java @@ -163,6 +163,29 @@ public class WindowsHelper { .executeAndGetOutput().stream().collect(Collectors.joining("\n")); } + public static String getExecutableDesciption(Path pathToExeFile) { + Executor exec = Executor.of("powershell", + "-NoLogo", + "-NoProfile", + "-Command", + "(Get-Item \\\"" + + pathToExeFile.toAbsolutePath() + + "\\\").VersionInfo | select FileDescription"); + + var lineIt = exec.dumpOutput().executeAndGetOutput().iterator(); + while (lineIt.hasNext()) { + var line = lineIt.next(); + if (line.trim().equals("FileDescription")) { + // Skip "---------------" and move to the description value + lineIt.next(); + return lineIt.next().trim(); + } + } + + throw new RuntimeException(String.format( + "Failed to get file description of [%s]", pathToExeFile)); + } + private static boolean isUserLocalInstall(JPackageCommand cmd) { return cmd.hasArgument("--win-per-user-install"); } diff --git a/test/jdk/tools/jpackage/share/AddLauncherTest.java b/test/jdk/tools/jpackage/share/AddLauncherTest.java index d1eca67b336d464f87994ec3b793cfa595e5c4f4..13d08e015eb9e83d90073aeb8ba33b269cb4879b 100644 --- a/test/jdk/tools/jpackage/share/AddLauncherTest.java +++ b/test/jdk/tools/jpackage/share/AddLauncherTest.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,7 +40,7 @@ import jdk.jpackage.test.CfgFile; * AddLauncherTest*.* installer. The output installer should provide the * same functionality as the default installer (see description of the default * installer in SimplePackageTest.java) plus install three extra application - * launchers. + * launchers with unique description ("LauncherName Description"). */ /* @@ -80,7 +80,8 @@ public class AddLauncherTest { PackageTest packageTest = new PackageTest().configureHelloApp(); packageTest.addInitializer(cmd -> { cmd.addArguments("--arguments", "Duke", "--arguments", "is", - "--arguments", "the", "--arguments", "King"); + "--arguments", "the", "--arguments", "King", + "--description", "AddLauncherTest Description"); }); new FileAssociations( @@ -89,14 +90,17 @@ public class AddLauncherTest { new AdditionalLauncher("Baz2") .setDefaultArguments() + .addRawProperties(Map.entry("description", "Baz2 Description")) .applyTo(packageTest); new AdditionalLauncher("foo") .setDefaultArguments("yep!") + .addRawProperties(Map.entry("description", "foo Description")) .applyTo(packageTest); new AdditionalLauncher("Bar") .setDefaultArguments("one", "two", "three") + .addRawProperties(Map.entry("description", "Bar Description")) .setIcon(GOLDEN_ICON) .applyTo(packageTest); diff --git a/test/langtools/jdk/javadoc/doclet/testInterface/TestInterface.java b/test/langtools/jdk/javadoc/doclet/testInterface/TestInterface.java index a435b831e7e33ed00f3a4aaf6252e50049015864..83530f323688a2af7759e5ef0b7811b2cf0ec2bd 100644 --- a/test/langtools/jdk/javadoc/doclet/testInterface/TestInterface.java +++ b/test/langtools/jdk/javadoc/doclet/testInterface/TestInterface.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 @@ -45,8 +45,8 @@ * In Child.html * Specified by: method in interface * Overrides: method in class Parent - * In otherwords the TypeParameter in scope should be used ex: Interface, Parent - and Child + * In other words the TypeParameter in scope should be used ex: Interface, Parent + * and Child */ import javadoc.tester.JavadocTester; diff --git a/test/langtools/jdk/javadoc/doclet/testOverriddenMethods/TestOverrideMethods.java b/test/langtools/jdk/javadoc/doclet/testOverriddenMethods/TestOverrideMethods.java index 785ddd5072fcbfb6dfbcddb2dcd7450a4c935e74..4e358149669c2fc81cfc75b2e6df36a9d04803f7 100644 --- a/test/langtools/jdk/javadoc/doclet/testOverriddenMethods/TestOverrideMethods.java +++ b/test/langtools/jdk/javadoc/doclet/testOverriddenMethods/TestOverrideMethods.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 @@ -23,7 +23,7 @@ /* * @test - * @bug 8157000 8192850 8182765 8223607 8261976 + * @bug 8157000 8192850 8182765 8223607 8261976 8281376 * @summary test the behavior of --override-methods option * @library ../../lib * @modules jdk.javadoc/jdk.javadoc.internal.tool @@ -569,4 +569,93 @@ public class TestOverrideMethods extends JavadocTester {

something
"""); } + + @Test + public void testPolymorphicDetail() { + javadoc("-d", "out-polymorphic-detail", + "-sourcepath", testSrc, + "--override-methods=detail", + "pkg8"); + + checkExit(Exit.OK); + + checkOutput("pkg8/C.html", true, + """ +
Overrides:
+
m1 in class \ + P
"""); + + checkOutput("pkg8/C.html", true, + """ +
Overrides:
+
m2 in class \ + P
"""); + + checkOutput("pkg8/C.html", true, + """ +
Overrides:
+
m3 in class \ + P
"""); + } + + @Test // results should be the same as that of "detail" + public void testPolymorphicDefault() { + javadoc("-d", "out-polymorphic-default", + "-sourcepath", testSrc, + "pkg8"); + + checkExit(Exit.OK); + + checkOutput("pkg8/C.html", true, + """ +
Overrides:
+
m1 in class \ + P
"""); + + checkOutput("pkg8/C.html", true, + """ +
Overrides:
+
m2 in class \ + P
"""); + + checkOutput("pkg8/C.html", true, + """ +
Overrides:
+
m3 in class \ + P
"""); + } + + @Test + public void testPolymorphicSummary() { + javadoc("-d", "out-polymorphic-summary", + "-sourcepath", testSrc, + "--override-methods=summary", + "pkg8"); + + checkExit(Exit.OK); + + checkOutput("pkg8/C.html", true, + """ +
Overrides:
+
m1 in class \ + GP
"""); + + checkOutput("pkg8/C.html", true, + """ +
Overrides:
+
m2 in class \ + GP
"""); + + checkOutput("pkg8/C.html", true, + """ +
Overrides:
+
m3 in class \ + GP
"""); + + checkOutput("pkg8/C.html", false, + """ +
Overrides:
+
m1 in class \ + P
"""); + } } diff --git a/test/langtools/jdk/javadoc/doclet/testOverriddenMethods/pkg3/I2.java b/test/langtools/jdk/javadoc/doclet/testOverriddenMethods/pkg3/I2.java index 8d1195273469faa5bb30bdad70bd35360f672c08..8c104391d86979b50a9414a93df22664142fce97 100644 --- a/test/langtools/jdk/javadoc/doclet/testOverriddenMethods/pkg3/I2.java +++ b/test/langtools/jdk/javadoc/doclet/testOverriddenMethods/pkg3/I2.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 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 @@ -25,6 +25,6 @@ package pkg3; public interface I2 { - public void foo(); + public void foo(); } diff --git a/test/langtools/jdk/javadoc/doclet/testOverriddenMethods/pkg3/I3.java b/test/langtools/jdk/javadoc/doclet/testOverriddenMethods/pkg3/I3.java index 59015817cd6d1ae841db7c3d989c57dcdbdec46f..5583ea96fc7c85bbd31a9ee4157f7876b2b8d793 100644 --- a/test/langtools/jdk/javadoc/doclet/testOverriddenMethods/pkg3/I3.java +++ b/test/langtools/jdk/javadoc/doclet/testOverriddenMethods/pkg3/I3.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 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 @@ -25,6 +25,6 @@ package pkg3; public interface I3 extends I4 { - public void foo(); + public void foo(); } diff --git a/test/langtools/jdk/javadoc/doclet/testOverriddenMethods/pkg3/I4.java b/test/langtools/jdk/javadoc/doclet/testOverriddenMethods/pkg3/I4.java index b0f52eaa91cb3e72b1b92acd25ed67f43a989835..6633fe1de166e4acdc12e43f4bfed990c466a5eb 100644 --- a/test/langtools/jdk/javadoc/doclet/testOverriddenMethods/pkg3/I4.java +++ b/test/langtools/jdk/javadoc/doclet/testOverriddenMethods/pkg3/I4.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 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 @@ -25,6 +25,6 @@ package pkg3; public interface I4 { - public void foo(); + public void foo(); } diff --git a/test/langtools/jdk/javadoc/doclet/testOverriddenMethods/pkg5/Classes.java b/test/langtools/jdk/javadoc/doclet/testOverriddenMethods/pkg5/Classes.java index 50048688ec3ab1b3f15abd6a686f3463f643900d..dd7b7125bde5443a6817313d0205e399bd4b27c9 100644 --- a/test/langtools/jdk/javadoc/doclet/testOverriddenMethods/pkg5/Classes.java +++ b/test/langtools/jdk/javadoc/doclet/testOverriddenMethods/pkg5/Classes.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,108 +33,108 @@ public class Classes { public void m7() {} } - public static class P extends GP { + public static class P extends GP { - /** A nested class in parent */ - public class PN{} + /** A nested class in parent */ + public class PN{} - /** A property in parent */ - private DoubleProperty rate; - public final void setRate(double l){} - public final double getRate(){return 1;} - public DoubleProperty rateProperty() {return null;} + /** A property in parent */ + private DoubleProperty rate; + public final void setRate(double l){} + public final double getRate(){return 1;} + public DoubleProperty rateProperty() {return null;} - /** A ctor in parent */ - public P() {} + /** A ctor in parent */ + public P() {} - /** - * A ctor in parent. - * @param s string - */ - public P(String s) {} + /** + * A ctor in parent. + * @param s string + */ + public P(String s) {} - /** field0 in parent */ - public int field0; + /** field0 in parent */ + public int field0; - /** field1 in parent */ - public int field1; + /** field1 in parent */ + public int field1; - // m0 in parent - public void m0() {} - - /** m1 in parent */ - public void m1() {} - - /** m2 in parent */ - public void m2() {} - - /** m3 in parent */ - public void m3() {} - - /** m4 in parent - @param k a key - @param v a value - */ - public void m4(K k, V v) {} - - // No comment - public void m5() {} - - // No comment - public void m6() {} - - /** {@inheritDoc} */ - public void m7() {} - - } - - public static class C extends P { + // m0 in parent + public void m0() {} - public C(String s) {} + /** m1 in parent */ + public void m1() {} - public int field1; + /** m2 in parent */ + public void m2() {} - /** A modified method */ - public void m1() {} + /** m3 in parent */ + public void m3() {} - /** {@inheritDoc} */ - public void m2() {} + /** m4 in parent + @param k a key + @param v a value + */ + public void m4(K k, V v) {} - // No comment method - public void m3() {} + // No comment + public void m5() {} - public void m4(String k, String v) {} + // No comment + public void m6() {} - // Do something else than the parent - public void m5() {} + /** {@inheritDoc} */ + public void m7() {} - /** A test of links to the methods in this class.

- * {@link m0}, - * {@link m1}, - * {@link m2}, - * {@link m3}, - * {@link m4}, - * {@link m5}, - * {@link m6}, - * {@link m7}, - * End of links - * - * @see #m0() - * @see #m1() - * @see #m2() - * @see #m3() - * @see #m4(String k, String v) - * @see #m5() - * @see #m6() - * @see #m7() - */ - public void m6() {} + } - /** m7 in Child. */ - public void m7() {} - } + public static class C extends P { + + public C(String s) {} + + public int field1; + + /** A modified method */ + public void m1() {} + + /** {@inheritDoc} */ + public void m2() {} + + // No comment method + public void m3() {} + + public void m4(String k, String v) {} + + // Do something else than the parent + public void m5() {} + + /** A test of links to the methods in this class.

+ * {@link m0}, + * {@link m1}, + * {@link m2}, + * {@link m3}, + * {@link m4}, + * {@link m5}, + * {@link m6}, + * {@link m7}, + * End of links + * + * @see #m0() + * @see #m1() + * @see #m2() + * @see #m3() + * @see #m4(String k, String v) + * @see #m5() + * @see #m6() + * @see #m7() + */ + public void m6() {} + + /** m7 in Child. */ + public void m7() {} + } - /** Tickle this {@link TestEnum#doSomething()} */ - public class DoubleProperty {} + /** Tickle this {@link TestEnum#doSomething()} */ + public class DoubleProperty {} } diff --git a/test/langtools/jdk/javadoc/doclet/testOverriddenMethods/pkg5/Interfaces.java b/test/langtools/jdk/javadoc/doclet/testOverriddenMethods/pkg5/Interfaces.java index dfac98fe4c0ef5e1153b465cda5b9296eb6bc5f2..cf3e5d95d54acdbc0c6e4ad0d8be7c303cdb388c 100644 --- a/test/langtools/jdk/javadoc/doclet/testOverriddenMethods/pkg5/Interfaces.java +++ b/test/langtools/jdk/javadoc/doclet/testOverriddenMethods/pkg5/Interfaces.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 @@ -24,67 +24,67 @@ package pkg5; public class Interfaces { - public interface A { + public interface A { - /** field f in A */ - public int f = 0; + /** field f in A */ + public int f = 0; - public static String QUOTE = "Winter is coming"; + public static String QUOTE = "Winter is coming"; - /** a documented static method */ - public static void msd() {} + /** a documented static method */ + public static void msd() {} - /* An undocumented static method */ - public static void msn() {} + /* An undocumented static method */ + public static void msn() {} - /** A property in parent */ - DoubleProperty rate = null; - public void setRate(double l); - public double getRate(); - public DoubleProperty rateProperty(); - // A support class - public interface DoubleProperty {} + /** A property in parent */ + DoubleProperty rate = null; + public void setRate(double l); + public double getRate(); + public DoubleProperty rateProperty(); + // A support class + public interface DoubleProperty {} - /** AA in A */ - public interface AA {} + /** AA in A */ + public interface AA {} - /** m0 in A */ - public void m0(); + /** m0 in A */ + public void m0(); - /** m1 in A */ - public void m1(); + /** m1 in A */ + public void m1(); - /** m2 in A */ - public void m2(); + /** m2 in A */ + public void m2(); - /** m3 in A */ - public void m3(); - } + /** m3 in A */ + public void m3(); + } - public interface B extends A { - // No comment - public void m0(); + public interface B extends A { + // No comment + public void m0(); - /** m1 in B */ - public void m1(); + /** m1 in B */ + public void m1(); - /** {@inheritDoc} */ - public void m2(); + /** {@inheritDoc} */ + public void m2(); - /** @throws Exception e */ - public void m3() throws Exception; + /** @throws Exception e */ + public void m3() throws Exception; - /** n in B */ - public void n(); - } + /** n in B */ + public void n(); + } - public interface C extends A, B { - /** m in C */ - public void m(); + public interface C extends A, B { + /** m in C */ + public void m(); - /** o in C */ - public void o(); - } + /** o in C */ + public void o(); + } /** * The child of all children. @@ -108,13 +108,13 @@ public class Interfaces { * @see #o */ public interface D extends A, B, C { - /** m in D */ - public void m(); + /** m in D */ + public void m(); - /** n in D */ - public void n(); + /** n in D */ + public void n(); - // no comment - public void o(); - } - } + // no comment + public void o(); + } +} diff --git a/test/langtools/jdk/javadoc/doclet/testOverriddenMethods/pkg6/Sub.java b/test/langtools/jdk/javadoc/doclet/testOverriddenMethods/pkg6/Sub.java index 694852f6d5e642e0f862b969c61651797725491c..7b85a4ad3d51e39959dd9d53cfb0297e3b05148a 100644 --- a/test/langtools/jdk/javadoc/doclet/testOverriddenMethods/pkg6/Sub.java +++ b/test/langtools/jdk/javadoc/doclet/testOverriddenMethods/pkg6/Sub.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 @@ -52,4 +52,3 @@ public class Sub extends Base { @Override public abstract Object m9(); } - diff --git a/src/hotspot/share/services/mallocTracker.inline.hpp b/test/langtools/jdk/javadoc/doclet/testOverriddenMethods/pkg8/C.java similarity index 70% rename from src/hotspot/share/services/mallocTracker.inline.hpp rename to test/langtools/jdk/javadoc/doclet/testOverriddenMethods/pkg8/C.java index b73e1d42adb2487799e6e0ddf69444ee273fbf7b..0bbfd17986bdba2866be6892ebee87146d77bc03 100644 --- a/src/hotspot/share/services/mallocTracker.inline.hpp +++ b/test/langtools/jdk/javadoc/doclet/testOverriddenMethods/pkg8/C.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 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 @@ -19,18 +19,29 @@ * 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_SERVICES_MALLOCTRACKER_INLINE_HPP -#define SHARE_SERVICES_MALLOCTRACKER_INLINE_HPP +package pkg8; -#include "services/mallocTracker.hpp" +public class C extends P { -#include "services/memTracker.hpp" + /** + * Child m1(). + * + * @param Child m1's type + */ + @Override + public void m1() {} -inline void* MallocTracker::get_base(void* memblock){ - return get_base(memblock, MemTracker::tracking_level()); -} + /** + * Child m2(). + */ + @Override + public void m2() {} -#endif // SHARE_SERVICES_MALLOCTRACKER_INLINE_HPP + /** + * Child m3(). + */ + @Override + public void m3() {} +} diff --git a/src/hotspot/cpu/s390/register_definitions_s390.cpp b/test/langtools/jdk/javadoc/doclet/testOverriddenMethods/pkg8/GP.java similarity index 65% rename from src/hotspot/cpu/s390/register_definitions_s390.cpp rename to test/langtools/jdk/javadoc/doclet/testOverriddenMethods/pkg8/GP.java index 2378d513799fe1f5222aae56b30749e3d7a60e20..393506a269fa4cbb3c466d84ba049620d3f865b4 100644 --- a/src/hotspot/cpu/s390/register_definitions_s390.cpp +++ b/test/langtools/jdk/javadoc/doclet/testOverriddenMethods/pkg8/GP.java @@ -1,6 +1,5 @@ /* - * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2016, 2017 SAP SE. 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 @@ -20,20 +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. - * */ -// Make sure the defines don't screw up the declarations later on in this file. -#define DONT_USE_REGISTER_DEFINES +package pkg8; -#include "precompiled.hpp" -#include "asm/assembler.hpp" -#include "asm/register.hpp" -#include "register_s390.hpp" -#include "interp_masm_s390.hpp" +public class GP { -REGISTER_DEFINITION(Register, noreg); + /** + * Grandparent m1(). + * + * @param Grandparent m1's type + */ + public void m1() {} -REGISTER_DEFINITION(FloatRegister, fnoreg); + /** + * Grandparent m2(). + * + * @param Grandparent m2's type + */ + public void m2() {} -REGISTER_DEFINITION(VectorRegister, vnoreg); + /** + * Grandparent m3(). + * + * @param Grandparent m3's type + */ + public void m3() {} +} diff --git a/src/hotspot/cpu/ppc/register_definitions_ppc.cpp b/test/langtools/jdk/javadoc/doclet/testOverriddenMethods/pkg8/P.java similarity index 68% rename from src/hotspot/cpu/ppc/register_definitions_ppc.cpp rename to test/langtools/jdk/javadoc/doclet/testOverriddenMethods/pkg8/P.java index c0bfd7db95af832e48fb7946c6a8e180993d7371..3f6135454b43648f8503b84fea7280ad6fd392a5 100644 --- a/src/hotspot/cpu/ppc/register_definitions_ppc.cpp +++ b/test/langtools/jdk/javadoc/doclet/testOverriddenMethods/pkg8/P.java @@ -1,6 +1,5 @@ /* - * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2012, 2015 SAP SE. 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 @@ -20,18 +19,20 @@ * 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. - * */ -// Make sure the defines don't screw up the declarations later on in this file. -#define DONT_USE_REGISTER_DEFINES +package pkg8; -#include "asm/register.hpp" +public class P extends GP { -REGISTER_DEFINITION(Register, noreg); + // note that while m1() and m2() are parameterized, m3() is not -REGISTER_DEFINITION(FloatRegister, fnoreg); + @Override + public void m1() {} -REGISTER_DEFINITION(VectorRegister, vnoreg); + @Override + public void m2() {} -REGISTER_DEFINITION(VectorSRegister, vsnoreg); + @Override + public void m3() {} +} diff --git a/test/langtools/jdk/javadoc/doclet/testPreview/TestPreview.java b/test/langtools/jdk/javadoc/doclet/testPreview/TestPreview.java index 46035e6eb71edf7323257c854be6f347243325aa..e3618aa1555c30d6c68edbef739a4e44a9f93309 100644 --- a/test/langtools/jdk/javadoc/doclet/testPreview/TestPreview.java +++ b/test/langtools/jdk/javadoc/doclet/testPreview/TestPreview.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 @@ -23,7 +23,7 @@ /* * @test - * @bug 8250768 8261976 + * @bug 8250768 8261976 8277300 8282452 * @summary test generated docs for items declared using preview * @library ../../lib * @modules jdk.javadoc/jdk.javadoc.internal.tool @@ -33,8 +33,6 @@ */ import java.nio.file.Paths; -import java.text.MessageFormat; -import java.util.ResourceBundle; import javadoc.tester.JavadocTester; public class TestPreview extends JavadocTester { @@ -101,4 +99,39 @@ public class TestPreview extends JavadocTester { """); } + + @Test + public void test8277300() { + javadoc("-d", "out-8277300", + "--add-exports", "java.base/jdk.internal.javac=api2", + "--source-path", Paths.get(testSrc, "api2").toAbsolutePath().toString(), + "--show-packages=all", + "api2/api"); + checkExit(Exit.OK); + + checkOutput("api2/api/API.html", true, + "

test()

", + "

testNoPreviewInSig()

", + "title=\"class or interface in java.util\" class=\"external-link\">List<APIPREVIEW>"); + checkOutput("api2/api/API2.html", true, + "API.test()PREVIEW", + "API.testNoPreviewInSig()PREVIEW", + "API3.test()PREVIEW"); + checkOutput("api2/api/API3.html", true, + ""); + } + + @Test + public void test8282452() { + javadoc("-d", "out-8282452", + "--patch-module", "java.base=" + Paths.get(testSrc, "api").toAbsolutePath().toString(), + "--add-exports", "java.base/preview=m", + "--source-path", Paths.get(testSrc, "api").toAbsolutePath().toString(), + "--show-packages=all", + "preview"); + checkExit(Exit.OK); + + checkOutput("java.base/preview/NoPreview.html", false, + "refers to one or more preview"); + } } diff --git a/test/langtools/jdk/javadoc/doclet/testPreview/api/preview/NoPreview.java b/test/langtools/jdk/javadoc/doclet/testPreview/api/preview/NoPreview.java new file mode 100644 index 0000000000000000000000000000000000000000..951b557ce6d387884df6e43f75f54bc248d578e2 --- /dev/null +++ b/test/langtools/jdk/javadoc/doclet/testPreview/api/preview/NoPreview.java @@ -0,0 +1,37 @@ +/* + * 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 preview; + +import jdk.internal.javac.PreviewFeature; +import jdk.internal.javac.PreviewFeature.Feature; + +public class NoPreview { + + @PreviewFeature(feature=Feature.TEST) + public T get() { + return null; + } + + @PreviewFeature(feature=Feature.TEST) + public static class T {} +} diff --git a/test/langtools/jdk/javadoc/doclet/testPreview/api2/api/API.java b/test/langtools/jdk/javadoc/doclet/testPreview/api2/api/API.java new file mode 100644 index 0000000000000000000000000000000000000000..f8dc37b8addb282ed195da8cf1aaa431f413fe0d --- /dev/null +++ b/test/langtools/jdk/javadoc/doclet/testPreview/api2/api/API.java @@ -0,0 +1,46 @@ +/* + * 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 api; + +import java.util.List; +import jdk.internal.javac.PreviewFeature; +import jdk.internal.javac.PreviewFeature.Feature; + +/** + *

{@link API#test()}

+ *

{@link API#testNoPreviewInSig()}

+ */ +@PreviewFeature(feature=Feature.TEST, reflective=false) +public class API { + + public API test() { + return null; + } + + public void testNoPreviewInSig() { + } + + public void typeArgs(List api) { + } +} diff --git a/test/langtools/jdk/javadoc/doclet/testPreview/api2/api/API2.java b/test/langtools/jdk/javadoc/doclet/testPreview/api2/api/API2.java new file mode 100644 index 0000000000000000000000000000000000000000..83c08c7d25856afdf83fc7e7b115b541175b0914 --- /dev/null +++ b/test/langtools/jdk/javadoc/doclet/testPreview/api2/api/API2.java @@ -0,0 +1,33 @@ +/* + * 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 api; + +/** + *

{@link API#test()} + *

{@link API#testNoPreviewInSig()} + *

{@link API3#test()} + */ +public class API2 { + +} diff --git a/test/langtools/jdk/javadoc/doclet/testPreview/api2/api/API3.java b/test/langtools/jdk/javadoc/doclet/testPreview/api2/api/API3.java new file mode 100644 index 0000000000000000000000000000000000000000..26ae586f27ce53d987a1e1488061c11ca39fb3a5 --- /dev/null +++ b/test/langtools/jdk/javadoc/doclet/testPreview/api2/api/API3.java @@ -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. + */ + +package api; + +import jdk.internal.javac.PreviewFeature; +import jdk.internal.javac.PreviewFeature.Feature; + +/** + * {@link API3#test()} + */ +public class API3 { + + @PreviewFeature(feature=Feature.TEST, reflective=false) + public void test() { + return null; + } + +} diff --git a/test/langtools/jdk/javadoc/doclet/testPreview/api2/module-info.java b/test/langtools/jdk/javadoc/doclet/testPreview/api2/module-info.java new file mode 100644 index 0000000000000000000000000000000000000000..0f9e3e5d6efce49cdade957a87c4ced6694cc1da --- /dev/null +++ b/test/langtools/jdk/javadoc/doclet/testPreview/api2/module-info.java @@ -0,0 +1,25 @@ +/* + * 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. + */ +module api2 { + exports api; +} diff --git a/test/langtools/jdk/javadoc/doclet/testPrivateClasses/TestPrivateClasses.java b/test/langtools/jdk/javadoc/doclet/testPrivateClasses/TestPrivateClasses.java index 91917705dd5f624f2915632b933fc9bb069e9e4a..9b23a45a2ddb3e61fe933cb5153e59e0e80c1330 100644 --- a/test/langtools/jdk/javadoc/doclet/testPrivateClasses/TestPrivateClasses.java +++ b/test/langtools/jdk/javadoc/doclet/testPrivateClasses/TestPrivateClasses.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 @@ -59,7 +59,7 @@ public class TestPrivateClasses extends JavadocTester { checkExit(Exit.OK); checkOutput("pkg/PublicChild.html", true, - // Field inheritence from non-public superclass. + // Field inheritance from non-public superclass. """ fieldInheritedFromParent""", // Method inheritance from non-public superclass. @@ -156,12 +156,12 @@ public class TestPrivateClasses extends JavadocTester { checkExit(Exit.OK); checkOutput("pkg/PublicChild.html", true, - // Field inheritence from non-public superclass. + // Field inheritance from non-public superclass. """ Fields inherited from class pkg.PrivateParent""", """ fieldInheritedFromParent""", - // Method inheritence from non-public superclass. + // Method inheritance from non-public superclass. """ Methods inherited from class pkg.PrivateParent""", """ @@ -195,7 +195,7 @@ public class TestPrivateClasses extends JavadocTester { ass="element-name type-name-label">PublicChild"""); checkOutput("pkg/PublicInterface.html", true, - // Field inheritence from non-public superinterface. + // Field inheritance from non-public superinterface. """ Fields inherited from interface pkg.PrivateInterface""", """ diff --git a/test/langtools/jdk/javadoc/doclet/testReturnTag/TestReturnTag.java b/test/langtools/jdk/javadoc/doclet/testReturnTag/TestReturnTag.java index 00d5c92c630055614385cceb9c35f8591cf8818a..4974f4e586ea1c91060ae945f9964750ef312c25 100644 --- a/test/langtools/jdk/javadoc/doclet/testReturnTag/TestReturnTag.java +++ b/test/langtools/jdk/javadoc/doclet/testReturnTag/TestReturnTag.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 @@ -23,7 +23,7 @@ /* * @test - * @bug 4490068 8075778 + * @bug 4490068 8075778 8283041 * @summary General tests for inline or block at-return tag * @library /tools/lib ../../lib * @modules jdk.javadoc/jdk.javadoc.internal.tool @@ -265,16 +265,30 @@ public class TestReturnTag extends JavadocTester { */ public int m() { return 0; } } + """, + """ + /** Comment. */ + public class X { + /** + * @author Jim + * {@return the result} + */ + public int m() { return 0; } + } """); javadoc("-d", base.resolve("out").toString(), "-sourcepath", src.toString(), - src.resolve("C.java").toString()); + src.resolve("C.java").toString(), + src.resolve("X.java").toString()); checkExit(Exit.OK); checkOutput(Output.OUT, true, "C.java:4: warning: {@return} not at beginning of description"); + checkOutput(Output.OUT, true, + "X.java:5: warning: {@return} not at beginning of description"); + checkOutput("C.html", true, """

Some text. Returns the result. More text.
diff --git a/test/langtools/jdk/javadoc/doclet/testSearch/TestSearch.java b/test/langtools/jdk/javadoc/doclet/testSearch/TestSearch.java index d25dba1df220967e5f2d6de6a473215b0b09897e..3d316571811499fe69b6203562affdedd6941ca4 100644 --- a/test/langtools/jdk/javadoc/doclet/testSearch/TestSearch.java +++ b/test/langtools/jdk/javadoc/doclet/testSearch/TestSearch.java @@ -411,7 +411,7 @@ public class TestSearch extends JavadocTester { """, """ - + """, """ """, @@ -684,7 +684,7 @@ public class TestSearch extends JavadocTester { checkFiles(expectedOutput, "search.js", "jquery-ui.overrides.css", - "script-dir/jquery-3.5.1.min.js", + "script-dir/jquery-3.6.0.min.js", "script-dir/jquery-ui.min.js", "script-dir/jquery-ui.min.css", "script-dir/jquery-ui.structure.min.css", diff --git a/test/langtools/jdk/javadoc/doclet/testSeeTag/TestSeeTag.java b/test/langtools/jdk/javadoc/doclet/testSeeTag/TestSeeTag.java index b6661acae52b5d1275023d7aa408af9cceeb2cbd..c65b522fd0823e2adcfe47e1ace89afa8e05a7ec 100644 --- a/test/langtools/jdk/javadoc/doclet/testSeeTag/TestSeeTag.java +++ b/test/langtools/jdk/javadoc/doclet/testSeeTag/TestSeeTag.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 @@ -23,15 +23,19 @@ /* * @test - * @bug 8017191 8182765 8200432 8239804 8250766 8262992 + * @bug 8017191 8182765 8200432 8239804 8250766 8262992 8281944 * @summary Javadoc is confused by at-link to imported classes outside of the set of generated packages - * @library ../../lib + * @library /tools/lib ../../lib * @modules jdk.javadoc/jdk.javadoc.internal.tool - * @build javadoc.tester.* + * @build toolbox.ToolBox javadoc.tester.* * @run main TestSeeTag */ import javadoc.tester.JavadocTester; +import toolbox.ToolBox; + +import java.io.IOException; +import java.nio.file.Path; public class TestSeeTag extends JavadocTester { @@ -110,4 +114,40 @@ public class TestSeeTag extends JavadocTester { """); } + + ToolBox tb = new ToolBox(); + + @Test + public void testErroneous() throws IOException { + Path src = Path.of("erroneous", "src"); + tb.writeJavaFiles(src, """ + package erroneous; + /** + * Comment. + * @see +
See Also:
+
+
    +
  • invalid input: '<a href="'
  • +
+
+ + """); + + } } diff --git a/test/langtools/jdk/javadoc/doclet/testTagInheritence/TestTagInheritence.java b/test/langtools/jdk/javadoc/doclet/testTagInheritence/TestTagInheritance.java similarity index 86% rename from test/langtools/jdk/javadoc/doclet/testTagInheritence/TestTagInheritence.java rename to test/langtools/jdk/javadoc/doclet/testTagInheritence/TestTagInheritance.java index 59189ff948e3a57784e4213712a19761a6fc8d7d..fece105d6ba2f1f2e735c4f45b3a7f71c1690690 100644 --- a/test/langtools/jdk/javadoc/doclet/testTagInheritence/TestTagInheritence.java +++ b/test/langtools/jdk/javadoc/doclet/testTagInheritence/TestTagInheritance.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 @@ -28,16 +28,15 @@ * @library ../../lib * @modules jdk.javadoc/jdk.javadoc.internal.tool * @build javadoc.tester.* - * @run main TestTagInheritence + * @run main TestTagInheritance */ -// TODO: Inheritence should be Inheritance! fix separately as noreg-trivial import javadoc.tester.JavadocTester; -public class TestTagInheritence extends JavadocTester { +public class TestTagInheritance extends JavadocTester { public static void main(String... args) throws Exception { - TestTagInheritence tester = new TestTagInheritence(); + TestTagInheritance tester = new TestTagInheritance(); tester.runTests(); } @@ -56,7 +55,7 @@ public class TestTagInheritence extends JavadocTester { //Test valid usage of inheritDoc tag. for (int i = 1; i < 40; i++) { - checkOutput("pkg/TestTagInheritence.html", true, + checkOutput("pkg/TestTagInheritance.html", true, "Test " + i + " passes"); } diff --git a/test/langtools/jdk/javadoc/doclet/testTagInheritence/pkg/TestTagInheritence.java b/test/langtools/jdk/javadoc/doclet/testTagInheritence/pkg/TestTagInheritance.java similarity index 91% rename from test/langtools/jdk/javadoc/doclet/testTagInheritence/pkg/TestTagInheritence.java rename to test/langtools/jdk/javadoc/doclet/testTagInheritence/pkg/TestTagInheritance.java index c2accc04b8116e3ed9796c40efeefbf37da3105e..60fecf4d09898f6e4878a0f1baaeeb2b887969f6 100644 --- a/test/langtools/jdk/javadoc/doclet/testTagInheritence/pkg/TestTagInheritence.java +++ b/test/langtools/jdk/javadoc/doclet/testTagInheritence/pkg/TestTagInheritance.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2003, 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,9 +26,9 @@ package pkg; import java.lang.*; import java.io.*; -public class TestTagInheritence extends TestAbstractClass implements TestInterface{ +public class TestTagInheritance extends TestAbstractClass implements TestInterface{ - //This method below tests tag inheritence from a class. + //This method below tests tag inheritance from a class. public String testAbstractClass_method1(int p1, int p2) throws java.io.IOException, @@ -57,7 +57,7 @@ java.lang.NullPointerException } /** - * This method tests @inheritDoc with an inteface. Here is the inherited comment:
+ * This method tests @inheritDoc with an interface. Here is the inherited comment:
* {@inheritDoc} * @param p1 {@inheritDoc} * @param p2 {@inheritDoc} diff --git a/test/langtools/jdk/javadoc/doclet/testThrowsInheritence/C.java b/test/langtools/jdk/javadoc/doclet/testThrowsInheritance/C.java similarity index 100% rename from test/langtools/jdk/javadoc/doclet/testThrowsInheritence/C.java rename to test/langtools/jdk/javadoc/doclet/testThrowsInheritance/C.java diff --git a/test/langtools/jdk/javadoc/doclet/testThrowsInheritence/Foo.java b/test/langtools/jdk/javadoc/doclet/testThrowsInheritance/Foo.java similarity index 100% rename from test/langtools/jdk/javadoc/doclet/testThrowsInheritence/Foo.java rename to test/langtools/jdk/javadoc/doclet/testThrowsInheritance/Foo.java diff --git a/test/langtools/jdk/javadoc/doclet/testThrowsInheritence/I.java b/test/langtools/jdk/javadoc/doclet/testThrowsInheritance/I.java similarity index 100% rename from test/langtools/jdk/javadoc/doclet/testThrowsInheritence/I.java rename to test/langtools/jdk/javadoc/doclet/testThrowsInheritance/I.java diff --git a/test/langtools/jdk/javadoc/doclet/testThrowsInheritence/Iface.java b/test/langtools/jdk/javadoc/doclet/testThrowsInheritance/Iface.java similarity index 100% rename from test/langtools/jdk/javadoc/doclet/testThrowsInheritence/Iface.java rename to test/langtools/jdk/javadoc/doclet/testThrowsInheritance/Iface.java diff --git a/test/langtools/jdk/javadoc/doclet/testThrowsInheritence/TestThrowsTagInheritence.java b/test/langtools/jdk/javadoc/doclet/testThrowsInheritance/TestThrowsTagInheritance.java similarity index 90% rename from test/langtools/jdk/javadoc/doclet/testThrowsInheritence/TestThrowsTagInheritence.java rename to test/langtools/jdk/javadoc/doclet/testThrowsInheritance/TestThrowsTagInheritance.java index 6409910e85f3b7deda4c3ca29c06b452350fc705..b02ddf1c467ebcb828875250233c7756cf011cc5 100644 --- a/test/langtools/jdk/javadoc/doclet/testThrowsInheritence/TestThrowsTagInheritence.java +++ b/test/langtools/jdk/javadoc/doclet/testThrowsInheritance/TestThrowsTagInheritance.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 @@ -30,16 +30,15 @@ * @library ../../lib * @modules jdk.javadoc/jdk.javadoc.internal.tool * @build javadoc.tester.* - * @run main TestThrowsTagInheritence + * @run main TestThrowsTagInheritance */ -// TODO: should be TestThrowsInheritance! import javadoc.tester.JavadocTester; -public class TestThrowsTagInheritence extends JavadocTester { +public class TestThrowsTagInheritance extends JavadocTester { public static void main(String... args) throws Exception { - TestThrowsTagInheritence tester = new TestThrowsTagInheritence(); + TestThrowsTagInheritance tester = new TestThrowsTagInheritance(); tester.runTests(); } diff --git a/test/langtools/jdk/javadoc/doclet/testThrowsInheritence/pkg/Abstract.java b/test/langtools/jdk/javadoc/doclet/testThrowsInheritance/pkg/Abstract.java similarity index 100% rename from test/langtools/jdk/javadoc/doclet/testThrowsInheritence/pkg/Abstract.java rename to test/langtools/jdk/javadoc/doclet/testThrowsInheritance/pkg/Abstract.java diff --git a/test/langtools/jdk/javadoc/doclet/testThrowsInheritence/pkg/Extender.java b/test/langtools/jdk/javadoc/doclet/testThrowsInheritance/pkg/Extender.java similarity index 100% rename from test/langtools/jdk/javadoc/doclet/testThrowsInheritence/pkg/Extender.java rename to test/langtools/jdk/javadoc/doclet/testThrowsInheritance/pkg/Extender.java diff --git a/test/langtools/jdk/javadoc/lib/javadoc/tester/JavadocTester.java b/test/langtools/jdk/javadoc/lib/javadoc/tester/JavadocTester.java index 1892fa2ebd5fdecff6d8d4c2a22e810d1f004d92..6c6415cf6de349809019912bedfa062623e333b4 100644 --- a/test/langtools/jdk/javadoc/lib/javadoc/tester/JavadocTester.java +++ b/test/langtools/jdk/javadoc/lib/javadoc/tester/JavadocTester.java @@ -58,6 +58,7 @@ import java.util.function.Function; import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.stream.Collectors; +import java.util.stream.Stream; import javax.tools.StandardJavaFileManager; @@ -266,39 +267,129 @@ public abstract class JavadocTester { /** * Run all methods annotated with @Test, followed by printSummary. - * Typically called on a tester object in main() + * The methods are invoked in the order found using getDeclaredMethods. + * The arguments for the invocation are provided {@link #getTestArgs(Method)}. + * + * Typically called on a tester object in main(). * + * @throws IllegalArgumentException if any test method does not have a recognized signature * @throws Exception if any errors occurred */ public void runTests() throws Exception { - runTests(m -> new Object[0]); + runTests(this::getTestArgs); } /** * Runs all methods annotated with @Test, followed by printSummary. + * The methods are invoked in the order found using getDeclaredMethods. + * The arguments for the invocation are provided by a given function. + * * Typically called on a tester object in main() * * @param f a function which will be used to provide arguments to each * invoked method - * @throws Exception if any errors occurred + * @throws Exception if any errors occurred while executing a test method */ public void runTests(Function f) throws Exception { - for (Method m: getClass().getDeclaredMethods()) { + for (Method m : getClass().getDeclaredMethods()) { Annotation a = m.getAnnotation(Test.class); if (a != null) { - try { - out.println("Running test " + m.getName()); - m.invoke(this, f.apply(m)); - } catch (InvocationTargetException e) { - Throwable cause = e.getCause(); - throw (cause instanceof Exception) ? ((Exception) cause) : e; - } + runTest(m, f); out.println(); } } printSummary(); } + /** + * Run the specified methods annotated with @Test, or all methods annotated + * with @Test if none are specified, followed by printSummary. + * The methods are invoked in the order given in the methodNames argument, + * or the order returned by getDeclaredMethods if no names are provided. + * The arguments for the invocation are provided {@link #getTestArgs(Method)}. + * + * Typically called on a tester object in main(String[] args), perhaps using + * args as the list of method names. + * + * @throws IllegalStateException if any methods annotated with @Test are overloaded + * @throws IllegalArgumentException if any of the method names does not name a suitable method + * @throws NullPointerException if {@code methodNames} is {@code null}, or if any of the names are {@code null} + * @throws Exception if any errors occurred while executing a test method + */ + public void runTests(String... methodNames) throws Exception { + runTests(this::getTestArgs, methodNames); + } + + /** + * Run the specified methods annotated with @Test, or all methods annotated + * with @Test if non are specified, followed by printSummary. + * The methods are invoked in the order given in the methodNames argument, + * or the order returned by getDeclaredMethods if no names are provided. + * The arguments for the invocation are provided {@link #getTestArgs(Method)}. + * + * Typically called on a tester object in main(String[] args), perhaps using + * args as the list of method names. + * + * @throws IllegalStateException if any methods annotated with @Test are overloaded + * @throws IllegalArgumentException if any of the method names does not name a suitable method + * @throws NullPointerException if {@code methodNames} is {@code null}, or if any of the names are {@code null} + * @throws Exception if any errors occurred while executing a test method + */ + public void runTests(Function f, String... methodNames) throws Exception { + if (methodNames.length == 0) { + runTests(f); + } else { + Map testMethods = Stream.of(getClass().getDeclaredMethods()) + .filter(this::isTestMethod) + .collect(Collectors.toMap(Method::getName, Function.identity(), + (o, n) -> { + throw new IllegalStateException("test method " + o.getName() + " is overloaded"); + })); + + List list = new ArrayList<>(); + for (String mn : methodNames) { + Method m = testMethods.get(mn); + if (m == null) { + throw new IllegalArgumentException("test method " + mn + " not found"); + } + list.add(m); + } + + for (Method m : list) { + runTest(m, f); + } + } + } + + protected boolean isTestMethod(Method m) { + return m.getAnnotation(Test.class) != null; + } + + protected Object[] getTestArgs(Method m) throws IllegalArgumentException { + Class[] paramTypes = m.getParameterTypes(); + if (paramTypes.length == 0) { + return new Object[] {}; + } else if (paramTypes.length == 1 && paramTypes[0] == Path.class) { + return new Object[] { Path.of(m.getName())}; + } else { + throw new IllegalArgumentException("unknown signature for method " + + m + Stream.of(paramTypes) + .map(Class::toString) + .collect(Collectors.joining(", ", "(", ")"))) ; + } + } + + protected void runTest(Method m, Function f) throws Exception { + try { + out.println("Running test " + m.getName()); + m.invoke(this, f.apply(m)); + } catch (InvocationTargetException e) { + Throwable cause = e.getCause(); + throw (cause instanceof Exception) ? ((Exception) cause) : e; + } + + } + /** * Runs javadoc. * The output directory used by this call and the final exit code diff --git a/test/langtools/jdk/javadoc/testJavadocTester/TestRunTests.java b/test/langtools/jdk/javadoc/testJavadocTester/TestRunTests.java new file mode 100644 index 0000000000000000000000000000000000000000..ae5c97fd5a6acee11baa5236edef646ad44063e3 --- /dev/null +++ b/test/langtools/jdk/javadoc/testJavadocTester/TestRunTests.java @@ -0,0 +1,272 @@ +/* + * 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 + * @bug 8272853 + * @summary improve `JavadocTester.runTests` + * @library /tools/lib/ ../lib + * @modules jdk.javadoc/jdk.javadoc.internal.tool + * @build toolbox.ToolBox javadoc.tester.* + * @run main TestRunTests + */ + +import javadoc.tester.JavadocTester; + +import java.io.PrintStream; +import java.lang.annotation.Annotation; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.List; +import java.util.Locale; +import java.util.Set; +import java.util.function.Function; + +public class TestRunTests { + @Retention(RetentionPolicy.RUNTIME) + public @interface RunTest { + } + + public static void main(String... args) throws Exception { + TestRunTests t = new TestRunTests(); + t.run(); + } + + PrintStream out = System.out; + + void run() throws Exception { + for (Method m : getClass().getDeclaredMethods()) { + Annotation a = m.getAnnotation(RunTest.class); + if (a != null) { + try { + out.println("Running " + m); + m.invoke(this); + out.println(); + } catch (InvocationTargetException e) { + error("Invocation Target Exception while running " + m + ": " + e.getCause()); + } catch (Exception e) { + error("Exception while running " + m + ": " + e); + } + } + } + out.flush(); + if (errors > 0) { + out.println(errors + " errors occurred"); + throw new Exception(errors + " errors occurred"); + } + } + + int errors; + + @RunTest + public void testNoArgs() throws Exception { + MainGroup g = new MainGroup(); + g.runTests(); + checkEqualUnordered(g.log, Set.of("m1()", "m2(m2)", "m3()", "m4(m4)")); + } + + @RunTest + public void testMethodNames() throws Exception { + MainGroup g = new MainGroup(); + g.runTests("m1", "m4", "m2"); + checkEqualOrdered(g.log, List.of("m1()", "m4(m4)", "m2(m2)")); + } + + @RunTest + public void testFunction() throws Exception { + Function f = m -> + switch (m.getName()) { + case "m1", "m3" -> new Object[]{}; + case "m2", "m4" -> new Object[]{Path.of(m.getName().toUpperCase(Locale.ROOT))}; + default -> throw new IllegalArgumentException(m.toString()); + }; + MainGroup g = new MainGroup(); + g.runTests(f); + checkEqualUnordered(g.log, Set.of("m1()", "m2(M2)", "m3()", "m4(M4)")); + } + + @RunTest + public void testFunctionMethodNames() throws Exception { + Function f = m -> + switch (m.getName()) { + case "m1", "m3" -> new Object[]{}; + case "m2", "m4" -> new Object[]{Path.of(m.getName().toUpperCase(Locale.ROOT))}; + default -> throw new IllegalArgumentException(m.toString()); + }; + MainGroup g = new MainGroup(); + g.runTests(f, "m1", "m4", "m2"); + checkEqualOrdered(g.log, List.of("m1()", "m4(M4)", "m2(M2)")); + } + + @RunTest + public void testMethodNotFound() throws Exception { + MainGroup g = new MainGroup(); + try { + g.runTests("m1", "m2", "mx", "m3", "m4"); + } catch (IllegalArgumentException e) { + g.log.add(e.toString()); + } + // implicit in the following is that the error was detected before any test methods were executed + checkEqualOrdered(g.log, List.of("java.lang.IllegalArgumentException: test method mx not found")); + } + + @RunTest + public void testInvalidSignature() throws Exception { + InvalidSignatureGroup g = new InvalidSignatureGroup(); + try { + g.runTests(); + } catch (IllegalArgumentException e) { + g.log.add(e.toString()); + } + // since the exception comes from the nested use of `getTestArgs`, it will be thrown + // when the test method is being called, and so is not constrained to be thrown + // before any test method is called + checkContainsAll(g.log, List.of("java.lang.IllegalArgumentException: unknown signature for method " + + "public void TestRunTests$InvalidSignatureGroup.invalidSignature(java.lang.Object)(class java.lang.Object)")); + } + + @RunTest + public void testOverloadedMethod() throws Exception { + OverloadGroup g = new OverloadGroup(); + try { + g.runTests("m1"); + } catch (IllegalStateException e) { + g.log.add(e.toString()); + } + // implicit in the following is that the error was detected before any test methods were executed + checkEqualOrdered(g.log, List.of("java.lang.IllegalStateException: test method m1 is overloaded")); + } + + void checkContainsAll(List found, List expect) { + if (!found.containsAll(expect)) { + out.println("Found: " + found); + out.println("Expect: " + expect); + error("Expected results not found"); + } + } + + void checkEqualOrdered(List found, List expect) { + if (!found.equals(expect)) { + out.println("Found: " + found); + out.println("Expect: " + expect); + error("Expected results not found"); + } + } + + void checkEqualUnordered(List found, Set expect) { + if (!(found.containsAll(expect) && expect.containsAll(found))) { + out.println("Found: " + found); + out.println("Expect: " + expect); + error("Expected results not found"); + } + } + + void error(String message) { + out.println("Error: " + message); + errors++; + } + + /** + * A group of tests to be executed by different overloads of {@code runTests}. + */ + public static class MainGroup extends JavadocTester { + List log = new ArrayList<>(); + + @Test + public void m1() { + log.add("m1()"); + checking("m1"); + passed("OK"); + } + + @Test + public void m2(Path p) { + log.add("m2(" + p.getFileName() + ")"); + checking("m2"); + passed("OK"); + } + + @Test + public void m3() { + log.add("m3()"); + checking("m3"); + passed("OK"); + } + + @Test + public void m4(Path p) { + log.add("m4(" + p.getFileName() + ")"); + checking("m4"); + passed("OK"); + } + } + + /** + * A group of tests containing one with an invalid (unrecognized) signature. + * The invalid signature should cause an exception when trying to run that test. + */ + public static class InvalidSignatureGroup extends JavadocTester { + List log = new ArrayList<>(); + + @Test + public void m1() { + log.add("m1()"); + checking("m1"); + passed("OK"); + } + + @Test + public void invalidSignature(Object o) { + log.add("invalidSignature(" + o + ")"); + checking("invalidSignature"); + passed("OK"); + } + } + + /** + * A group of tests including an overloaded test method. + * The overload should cause an exception when trying to run that test by name. + */ + public static class OverloadGroup extends JavadocTester { + List log = new ArrayList<>(); + + @Test + public void m1() { + log.add("m1()"); + checking("m1"); + passed("OK"); + } + + @Test + public void m1(Path p) { + log.add("m1(" + p + ")"); + checking("m1"); + passed("OK"); + } + } +} diff --git a/test/langtools/jdk/javadoc/tool/api/basic/APITest.java b/test/langtools/jdk/javadoc/tool/api/basic/APITest.java index a0d68d8540333f72771f2f694823337783a8b4f5..3a5ddda8261824fed9586854f581e523162446fc 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 @@ class APITest { "help-doc.html", "index-all.html", "index.html", - "script-dir/jquery-3.5.1.min.js", + "script-dir/jquery-3.6.0.min.js", "script-dir/jquery-ui.min.js", "script-dir/jquery-ui.min.css", "script-dir/jquery-ui.structure.min.css", diff --git a/test/langtools/jdk/javadoc/tool/api/basic/JavadocTaskImplTest.java b/test/langtools/jdk/javadoc/tool/api/basic/JavadocTaskImplTest.java index 1a8f1d89f775e1c045b603a28c60595d6fd8d09a..ab84566e827623b4873f210f1cc9c16850389491 100644 --- a/test/langtools/jdk/javadoc/tool/api/basic/JavadocTaskImplTest.java +++ b/test/langtools/jdk/javadoc/tool/api/basic/JavadocTaskImplTest.java @@ -104,7 +104,7 @@ public class JavadocTaskImplTest extends APITest { File outDir = getOutDir(); fm.setLocation(DocumentationTool.Location.DOCUMENTATION_OUTPUT, Arrays.asList(outDir)); try { - DocumentationTask t = new JavadocTaskImpl(c, null, null, files);; + DocumentationTask t = new JavadocTaskImpl(c, null, null, files); error("getTask succeeded, no exception thrown"); } catch (NullPointerException e) { System.err.println("exception caught as expected: " + e); diff --git a/test/langtools/jdk/jshell/VariablesTest.java b/test/langtools/jdk/jshell/VariablesTest.java index 4224331b331c88f74fd213370defd7214e0a4f56..be957d5065e08a4a7f3963f111a9f32a0cb4b4a0 100644 --- a/test/langtools/jdk/jshell/VariablesTest.java +++ b/test/langtools/jdk/jshell/VariablesTest.java @@ -340,7 +340,7 @@ public class VariablesTest extends KullaTesting { //assertEquals(getState().source(snippet), src); //assertEquals(snippet, undefKey); assertEquals(getState().status(undefKey), RECOVERABLE_NOT_DEFINED); - List unr = getState().unresolvedDependencies((VarSnippet) undefKey).collect(toList());; + List unr = getState().unresolvedDependencies((VarSnippet) undefKey).collect(toList()); assertEquals(unr.size(), 1); assertEquals(unr.get(0), "class undefined"); assertVariables(variable("undefined", "d")); diff --git a/test/langtools/tools/doclint/RunTest.java b/test/langtools/tools/doclint/RunTest.java index 2d287136b479d06fdf7b35677add31e82ee9ad12..aff4b6c855babdd78218626c2a76d3a18e2f7406 100644 --- a/test/langtools/tools/doclint/RunTest.java +++ b/test/langtools/tools/doclint/RunTest.java @@ -59,7 +59,7 @@ public class RunTest { System.err.println("test: " + m.getName()); try { StringWriter sw = new StringWriter(); - PrintWriter pw = new PrintWriter(sw);; + PrintWriter pw = new PrintWriter(sw); m.invoke(this, new Object[] { pw }); String out = sw.toString(); System.err.println(">>> " + out.replace("\n", "\n>>> ")); diff --git a/test/langtools/tools/javac/8074306/TestSyntheticNullChecks.java b/test/langtools/tools/javac/8074306/TestSyntheticNullChecks.java index 137e15c15bfdd238cd8544669f0b20a22306e04b..c4b8843cebc0408eafc55db309429b606c770b0c 100644 --- a/test/langtools/tools/javac/8074306/TestSyntheticNullChecks.java +++ b/test/langtools/tools/javac/8074306/TestSyntheticNullChecks.java @@ -27,7 +27,7 @@ * @summary NULLCHK is emitted as Object.getClass * @compile -source 7 -target 7 TestSyntheticNullChecks.java * @run main TestSyntheticNullChecks 7 - * @clean TestSyntheticNullChecks* + * @clean * * @compile TestSyntheticNullChecks.java * @run main TestSyntheticNullChecks 9 */ diff --git a/test/langtools/tools/javac/StringConcat/TestIndyStringConcat.java b/test/langtools/tools/javac/StringConcat/TestIndyStringConcat.java index 7576503efedb33d26c3e020b0bd608b9b4fee78a..1c4d830c6eb7dd82118d0b13d5d2bf159ac07449 100644 --- a/test/langtools/tools/javac/StringConcat/TestIndyStringConcat.java +++ b/test/langtools/tools/javac/StringConcat/TestIndyStringConcat.java @@ -34,23 +34,23 @@ import java.io.File; * @summary Test that StringConcat is working for JDK >= 9 * @modules jdk.jdeps/com.sun.tools.classfile * - * @clean TestIndyStringConcat* + * @clean * * @compile -source 7 -target 7 TestIndyStringConcat.java * @run main TestIndyStringConcat false * - * @clean TestIndyStringConcat* + * @clean * * @compile -source 8 -target 8 TestIndyStringConcat.java * @run main TestIndyStringConcat false * - * @clean TestIndyStringConcat* + * @clean * * @compile -XDstringConcat=inline -source 9 -target 9 TestIndyStringConcat.java * @run main TestIndyStringConcat false * - * @clean TestIndyStringConcat* + * @clean * * @compile -XDstringConcat=indy -source 9 -target 9 TestIndyStringConcat.java * @run main TestIndyStringConcat true * - * @clean TestIndyStringConcat* + * @clean * * @compile -XDstringConcat=indyWithConstants -source 9 -target 9 TestIndyStringConcat.java * @run main TestIndyStringConcat true */ diff --git a/test/langtools/tools/javac/generics/inference/4954546/T4954546.java b/test/langtools/tools/javac/generics/inference/4954546/T4954546.java index 7ce1dcb5a3a7e9e0fd4d49f8d00b09f08c50cb33..456624b8333a879133c52b1838da227542068e7d 100644 --- a/test/langtools/tools/javac/generics/inference/4954546/T4954546.java +++ b/test/langtools/tools/javac/generics/inference/4954546/T4954546.java @@ -46,7 +46,7 @@ public class T4954546 { f(true, new A(), new B()); } static void f(boolean cond, A a, B b) { - (cond?a:b).f();; - (cond?a:b).g();; + (cond?a:b).f(); + (cond?a:b).g(); } } diff --git a/test/langtools/tools/javac/launcher/SourceLauncherTest.java b/test/langtools/tools/javac/launcher/SourceLauncherTest.java index 1b8fc23e67979e9228852680992cc7e689e0fe7e..a052f087af6047b9b71d1583b9b1768edf3205b8 100644 --- a/test/langtools/tools/javac/launcher/SourceLauncherTest.java +++ b/test/langtools/tools/javac/launcher/SourceLauncherTest.java @@ -213,48 +213,22 @@ public class SourceLauncherTest extends TestRunner { } @Test - public void testPermissions(Path base) throws IOException { - // does not work on exploded image, because the default policy file assumes jrt:; skip the test - if (Files.exists(Path.of(System.getProperty("java.home")).resolve("modules"))) { - out.println("JDK using exploded modules; test skipped"); - return; - } - - Path policyFile = base.resolve("test.policy"); - Path sourceFile = base.resolve("TestPermissions.java"); - - tb.writeFile(policyFile, - "grant codeBase \"jrt:/jdk.compiler\" {\n" + - " permission java.security.AllPermission;\n" + - "};\n" + - "grant codeBase \"" + sourceFile.toUri().toURL() + "\" {\n" + - " permission java.util.PropertyPermission \"user.dir\", \"read\";\n" + - "};\n"); - + public void testSecurityManager(Path base) throws IOException { + Path sourceFile = base.resolve("HelloWorld.java"); tb.writeJavaFiles(base, - "import java.net.URL;\n" + - "class TestPermissions {\n" + - " public static void main(String... args) {\n" + - " System.out.println(\"user.dir=\" + System.getProperty(\"user.dir\"));\n" + - " try {\n" + - " System.setProperty(\"user.dir\", \"\");\n" + - " System.out.println(\"no exception\");\n" + - " System.exit(1);\n" + - " } catch (SecurityException e) {\n" + - " System.out.println(\"exception: \" + e);\n" + - " }\n" + - " }\n" + - "}"); + "class HelloWorld {\n" + + " public static void main(String... args) {\n" + + " System.out.println(\"Hello World!\");\n" + + " }\n" + + "}"); String log = new JavaTask(tb) - .vmOptions("-Djava.security.manager", "-Djava.security.policy=" + policyFile) + .vmOptions("-Djava.security.manager=default") .className(sourceFile.toString()) - .run(Task.Expect.SUCCESS) - .getOutput(Task.OutputKind.STDOUT); - checkEqual("stdout", log.trim(), - "user.dir=" + System.getProperty("user.dir") + "\n" + - "exception: java.security.AccessControlException: " + - "access denied (\"java.util.PropertyPermission\" \"user.dir\" \"write\")"); + .run(Task.Expect.FAIL) + .getOutput(Task.OutputKind.STDERR); + checkContains("stderr", log, + "error: cannot use source-code launcher with a security manager enabled"); } public void testSystemProperty(Path base) throws IOException { @@ -710,6 +684,14 @@ public class SourceLauncherTest extends TestRunner { } } + void checkContains(String name, String found, String expect) { + expect = expect.replace("\n", tb.lineSeparator); + out.println(name + ": " + found); + if (!found.contains(expect)) { + error("Expected output not found: " + expect); + } + } + void checkEqual(String name, List found, List expect) { out.println(name + ": " + found); tb.checkEqual(expect, found); diff --git a/test/langtools/tools/javac/platform/CanHandleClassFilesTest.java b/test/langtools/tools/javac/platform/CanHandleClassFilesTest.java index 8afdf54f40d20dcac1fc12bda8397c46d69ef091..ae4f525e4ee125497567bff46e80550e931606f3 100644 --- a/test/langtools/tools/javac/platform/CanHandleClassFilesTest.java +++ b/test/langtools/tools/javac/platform/CanHandleClassFilesTest.java @@ -64,7 +64,7 @@ public class CanHandleClassFilesTest { Path test = d.resolve("make/langtools/src/classes/build/tools/symbolgenerator/CreateSymbols.java"); if (Files.exists(test)) { createSymbols = test; - includeList = d.resolve("make/data/symbols/include.list"); + includeList = d.resolve("src/jdk.compiler/share/data/symbols/include.list"); break; } } diff --git a/test/langtools/tools/javac/processing/model/element/TestElementKindPredicates.java b/test/langtools/tools/javac/processing/model/element/TestElementKindPredicates.java index 77b31540926b48efdd9858b1346fff9db614a2d5..49b3c72ac39b05d812fd2c142a14f7c635dd279d 100644 --- a/test/langtools/tools/javac/processing/model/element/TestElementKindPredicates.java +++ b/test/langtools/tools/javac/processing/model/element/TestElementKindPredicates.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 @@ -23,7 +23,7 @@ /* * @test - * @bug 8222430 + * @bug 8222430 8282411 * @summary Test various predicates of ElementKind. */ @@ -38,24 +38,64 @@ public class TestElementKindPredicates { public static void main(String... args) { Set ALL_KINDS = Set.of(ElementKind.values()); - // isClass: Returns true if this is a kind of class: either CLASS or ENUM. + // isClass: Returns true if this is a kind of class:CLASS, ENUM, or RECORD. test(ALL_KINDS, (ElementKind k) -> Set.of(ElementKind.CLASS, ElementKind.ENUM, ElementKind.RECORD).contains(k), (ElementKind k) -> k.isClass(), "isClass"); - // isField: Returns true if this is a kind of field: either FIELD or ENUM_CONSTANT. + // isField: Returns true if this is a kind of field: one of + // FIELD or ENUM_CONSTANT. test(ALL_KINDS, (ElementKind k) -> Set.of(ElementKind.FIELD, ElementKind.ENUM_CONSTANT).contains(k), (ElementKind k) -> k.isField(), "isField"); - // isInterface: Returns true if this is a kind of interface: either INTERFACE or ANNOTATION_TYPE. + // isInterface: Returns true if this is a kind of interface: + // either INTERFACE or ANNOTATION_TYPE. test(ALL_KINDS, (ElementKind k) -> Set.of(ElementKind.INTERFACE, ElementKind.ANNOTATION_TYPE).contains(k), (ElementKind k) -> k.isInterface(), "isInterface"); + + // isDeclaredType: Returns true if this is a kind of class or interface + test(ALL_KINDS, + (ElementKind k) -> Set.of(ElementKind.CLASS, + ElementKind.ENUM, + ElementKind.RECORD, + ElementKind.INTERFACE, + ElementKind.ANNOTATION_TYPE).contains(k), + (ElementKind k) -> k.isDeclaredType(), "isDeclaredType"); + + // isExecutable: Returns true if this is a kind of executable: one of + // METHOD, CONSTRUCTOR, STATIC_INIT, INSTANCE_INIT + test(ALL_KINDS, + (ElementKind k) -> Set.of(ElementKind.METHOD, + ElementKind.CONSTRUCTOR, + ElementKind.STATIC_INIT, + ElementKind.INSTANCE_INIT).contains(k), + (ElementKind k) -> k.isExecutable(), "isExecutable"); + + // isInitializer: Returns true if this is a kind of initializer: one of + // STATIC_INIT, INSTANCE_INIT + test(ALL_KINDS, + (ElementKind k) -> Set.of(ElementKind.STATIC_INIT, + ElementKind.INSTANCE_INIT).contains(k), + (ElementKind k) -> k.isInitializer(), "isInitializer"); + + // isVariable: Returns true if this is a kind of variable: one of + // ENUM_CONSTANT, FIELD, PARAMETER, LOCAL_VARIABLE, EXCEPTION_PARAMETER + // RESOURCE_VARIABLE, BINDING_VARIABLE + test(ALL_KINDS, + (ElementKind k) -> Set.of(ElementKind.ENUM_CONSTANT, + ElementKind.FIELD, + ElementKind.PARAMETER, + ElementKind.LOCAL_VARIABLE, + ElementKind.EXCEPTION_PARAMETER, + ElementKind.RESOURCE_VARIABLE, + ElementKind.BINDING_VARIABLE).contains(k), + (ElementKind k) -> k.isVariable(), "isVariable"); } private static void test(Set kinds, diff --git a/test/langtools/tools/javac/sym/ElementStructureTest.java b/test/langtools/tools/javac/sym/ElementStructureTest.java index db5ae5f4582a14dd8de894ddc2544e2e18b1ece3..791785b24521ef5db20b4a858e6405aa872bfaf3 100644 --- a/test/langtools/tools/javac/sym/ElementStructureTest.java +++ b/test/langtools/tools/javac/sym/ElementStructureTest.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 @@ -104,7 +104,7 @@ import toolbox.ToolBox; /**To generate the hash values for version N, invoke this class like: * - * java ElementStructureTest generate-hashes $LANGTOOLS_DIR/make/data/symbols/include.list ( N)+ + * java ElementStructureTest generate-hashes $LANGTOOLS_DIR/src/jdk.compiler/share/data/symbols/include.list ( N)+ * * Where is the file produced by make/src/classes/build/tools/symbolgenerator/Probe.java. * So, to produce hashes for 6, 7 and 8, this command can be used: @@ -113,11 +113,11 @@ import toolbox.ToolBox; * * To inspect differences between the actual and expected output for version N, invoke this class like: * - * java ElementStructureTest generate-output $LANGTOOLS_DIR/make/data/symbols/include.list ( N )+ + * java ElementStructureTest generate-output $LANGTOOLS_DIR/src/jdk.compiler/share/data/symbols/include.list ( N )+ * * For example, to get the actual and expected output for 6 in /tmp/actual and /tmp/expected, respectively: * - * java ElementStructureTest generate-output $LANGTOOLS_DIR/make/data/symbols/include.list classes-6 6 /tmp/actual /tmp/expected + * java ElementStructureTest generate-output $LANGTOOLS_DIR/src/jdk.compiler/share/data/symbols/include.list classes-6 6 /tmp/actual /tmp/expected */ public class ElementStructureTest { diff --git a/test/langtools/tools/javac/warnings/suppress/SuppressWarningsPackage.java b/test/langtools/tools/javac/warnings/suppress/SuppressWarningsPackage.java new file mode 100644 index 0000000000000000000000000000000000000000..3c6e13fa1fd203d18c01d2df9652eecf714500be --- /dev/null +++ b/test/langtools/tools/javac/warnings/suppress/SuppressWarningsPackage.java @@ -0,0 +1,209 @@ +/* + * 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 8280866 + * @summary Verify SuppressWarnings works on package clauses and modules. + * @library /tools/lib + * @modules jdk.compiler/com.sun.tools.javac.api + * @modules jdk.compiler/com.sun.tools.javac.main + * @build toolbox.JavacTask toolbox.TestRunner toolbox.ToolBox + * @run main SuppressWarningsPackage + */ + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.Arrays; +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 SuppressWarningsPackage extends TestRunner { + public static void main(String... args) throws Exception { + SuppressWarningsPackage t = new SuppressWarningsPackage(); + t.runTests(m -> new Object[] { Paths.get(m.getName()) }); + } + + private final ToolBox tb = new ToolBox(); + + public SuppressWarningsPackage() throws IOException { + super(System.err); + } + + @Test + public void testSuppressWarningsOnPackageInfo(Path base) throws IOException { + Path src = base.resolve("src"); + Path classes = Files.createDirectories(base.resolve("classes")); + TestCase[] testCases = new TestCase[] { + new TestCase("", + "package-info.java:1:2: compiler.warn.has.been.deprecated: test.DeprecatedAnn, test", + "package-info.java:1:16: compiler.warn.has.been.deprecated: test.DeprecatedClass, test", + "Use.java:2:2: compiler.warn.has.been.deprecated: test.DeprecatedAnn, test", + "Use.java:2:16: compiler.warn.has.been.deprecated: test.DeprecatedClass, test", + "4 warnings"), + new TestCase("@SuppressWarnings(\"deprecation\")", + "Use.java:2:2: compiler.warn.has.been.deprecated: test.DeprecatedAnn, test", + "Use.java:2:16: compiler.warn.has.been.deprecated: test.DeprecatedClass, test", + "2 warnings") + }; + for (TestCase tc : testCases) { + tb.writeJavaFiles(src, + """ + @DeprecatedAnn(DeprecatedClass.class) + # + package test; + """.replace("#", tc.sw), + """ + package test; + @Deprecated + public @interface DeprecatedAnn { + public Class value(); + } + """, + """ + package test; + @Deprecated + public class DeprecatedClass { + public static class Nested {} + } + """, + """ + package test; + @DeprecatedAnn(DeprecatedClass.class) + public class Use {} + """); + + List log = new JavacTask(tb) + .outdir(classes) + .files(tb.findJavaFiles(src)) + .options("-XDrawDiagnostics", + "-Xlint:deprecation") + .run(Expect.SUCCESS) + .writeAll() + .getOutputLines(OutputKind.DIRECT); + + if (!Objects.equals(log, List.of(tc.expectedOutput))) { + error("Unexpected output, expected:\n" + Arrays.toString(tc.expectedOutput) + + "\nactual:\n" + log); + } + } + } + + @Test + public void testSuppressWarningsOnModuleInfo(Path base) throws IOException { + Path src = base.resolve("src"); + Path classes = Files.createDirectories(base.resolve("classes")); + TestCase[] testCases = new TestCase[] { + new TestCase("", + "module-info.java:3:12: compiler.warn.has.been.deprecated: test.DeprecatedClass, test", + "module-info.java:4:2: compiler.warn.has.been.deprecated: test.DeprecatedAnn, test", + "module-info.java:4:16: compiler.warn.has.been.deprecated: test.DeprecatedClass, test", + "module-info.java:7:14: compiler.warn.has.been.deprecated: test.Service, test", + "module-info.java:8:18: compiler.warn.has.been.deprecated: test.Service, test", + "module-info.java:8:36: compiler.warn.has.been.deprecated: test.ServiceImpl, test", + "package-info.java:1:2: compiler.warn.has.been.deprecated: test.DeprecatedAnn, test", + "package-info.java:1:16: compiler.warn.has.been.deprecated: test.DeprecatedClass, test", + "Use.java:2:2: compiler.warn.has.been.deprecated: test.DeprecatedAnn, test", + "Use.java:2:16: compiler.warn.has.been.deprecated: test.DeprecatedClass, test", + "10 warnings"), + new TestCase("@SuppressWarnings(\"deprecation\")", + "module-info.java:3:12: compiler.warn.has.been.deprecated: test.DeprecatedClass, test", + "package-info.java:1:2: compiler.warn.has.been.deprecated: test.DeprecatedAnn, test", + "package-info.java:1:16: compiler.warn.has.been.deprecated: test.DeprecatedClass, test", + "Use.java:2:2: compiler.warn.has.been.deprecated: test.DeprecatedAnn, test", + "Use.java:2:16: compiler.warn.has.been.deprecated: test.DeprecatedClass, test", + "5 warnings") + }; + for (TestCase tc : testCases) { + tb.writeJavaFiles(src, + """ + import test.DeprecatedAnn; + import test.DeprecatedClass; + import test.DeprecatedClass.Nested; + @DeprecatedAnn(DeprecatedClass.class) + # + module m { + uses test.Service; + provides test.Service with test.ServiceImpl; + } + """.replace("#", tc.sw), + """ + @DeprecatedAnn(DeprecatedClass.class) + package test; + """, + """ + package test; + @Deprecated + public @interface DeprecatedAnn { + public Class value(); + } + """, + """ + package test; + @Deprecated + public class DeprecatedClass { + public static class Nested {} + } + """, + """ + package test; + @Deprecated + public interface Service {} + """, + """ + package test; + @Deprecated + public class ServiceImpl implements Service {} + """, + """ + package test; + @DeprecatedAnn(DeprecatedClass.class) + public class Use {} + """); + + List log = new JavacTask(tb) + .outdir(classes) + .files(tb.findJavaFiles(src)) + .options("-XDrawDiagnostics", + "-Xlint:deprecation") + .run(Expect.SUCCESS) + .writeAll() + .getOutputLines(OutputKind.DIRECT); + + if (!Objects.equals(log, List.of(tc.expectedOutput))) { + error("Unexpected output, expected:\n" + Arrays.toString(tc.expectedOutput) + + "\nactual:\n" + log); + } + } + } + + record TestCase(String sw, String... expectedOutput) {} +} diff --git a/test/lib/jdk/test/lib/SecurityTools.java b/test/lib/jdk/test/lib/SecurityTools.java index 30da87f2d32fb5f528a3c3d1f21ae2db76e09340..36019a00e879b970a4e39ea531b2394c1450d3ff 100644 --- a/test/lib/jdk/test/lib/SecurityTools.java +++ b/test/lib/jdk/test/lib/SecurityTools.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 @@ -40,8 +40,8 @@ import jdk.test.lib.process.ProcessTools; * 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. {@code -Jvm-options} is supported - * as an argument. + * not block because of entropy scarcity. An argument can be a normal string, + * {@code -Jvm-options}, or {@code $sysProp}. */ public class SecurityTools { @@ -66,6 +66,8 @@ public class SecurityTools { } else if (Platform.isWindows() && arg.isEmpty()) { // JDK-6518827: special handling for empty argument on Windows launcher.addToolArg("\"\""); + } else if (arg.length() > 1 && arg.charAt(0) == '$') { + launcher.addToolArg(System.getProperty(arg.substring(1))); } else { launcher.addToolArg(arg); } diff --git a/test/lib/jdk/test/lib/cds/CDSOptions.java b/test/lib/jdk/test/lib/cds/CDSOptions.java index cbc11db777b1a55d1f34930c122614c0e6657d9c..a60afb90aed29b2b7c2c25e3d182af0aebc1a6e4 100644 --- a/test/lib/jdk/test/lib/cds/CDSOptions.java +++ b/test/lib/jdk/test/lib/cds/CDSOptions.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 @@ -56,6 +56,11 @@ public class CDSOptions { return this; } + public CDSOptions addSuffix(ArrayList suffix) { + for (String s : suffix) this.suffix.add(s); + return this; + } + public CDSOptions addSuffix(String... suffix) { for (String s : suffix) this.suffix.add(s); return this; diff --git a/test/micro/org/openjdk/bench/java/lang/StringDecode.java b/test/micro/org/openjdk/bench/java/lang/StringDecode.java index 186d2aed6d95b99a5c1f06ab5b50c48083818075..ee4f8df7c734f21eb235f1c380843c66ae5dde42 100644 --- a/test/micro/org/openjdk/bench/java/lang/StringDecode.java +++ b/test/micro/org/openjdk/bench/java/lang/StringDecode.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 @@ -22,17 +22,7 @@ */ package org.openjdk.bench.java.lang; -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.Param; -import org.openjdk.jmh.annotations.Scope; -import org.openjdk.jmh.annotations.Setup; -import org.openjdk.jmh.annotations.State; -import org.openjdk.jmh.annotations.Warmup; +import org.openjdk.jmh.annotations.*; import org.openjdk.jmh.infra.Blackhole; import java.nio.charset.Charset; @@ -40,28 +30,30 @@ import java.util.concurrent.TimeUnit; @BenchmarkMode(Mode.AverageTime) @OutputTimeUnit(TimeUnit.NANOSECONDS) -@Fork(value = 3) -@Warmup(iterations = 5, time = 2) +@Fork(value = 2) +@Warmup(iterations = 5, time = 3) @Measurement(iterations = 5, time = 3) @State(Scope.Thread) public class StringDecode { - @Param({"US-ASCII", "ISO-8859-1", "UTF-8", "MS932", "ISO-8859-6", "ISO-2022-KR"}) + // Reduced by default to only UTF-8, previous coverage: + // @Param({"US-ASCII", "ISO-8859-1", "UTF-8", "MS932", "ISO-8859-6", "ISO-2022-KR"}) + @Param({"UTF-8"}) private String charsetName; private Charset charset; private byte[] asciiString; + private byte[] longAsciiString; private byte[] utf16String; - private byte[] longUtf16String; + private byte[] longUtf16EndString; private byte[] longUtf16StartString; - private byte[] longLatin1String; + private byte[] longUtf16OnlyString; + private byte[] latin1String; + private byte[] longLatin1EndString; + private byte[] longLatin1StartString; + private byte[] longLatin1OnlyString; - @Setup - public void setup() { - charset = Charset.forName(charsetName); - asciiString = "ascii string".getBytes(charset); - utf16String = "UTF-\uFF11\uFF16 string".getBytes(charset); - longUtf16String = """ + private static final String LOREM = """ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aliquam ac sem eu urna egestas placerat. Etiam finibus ipsum nulla, non mattis dolor cursus a. Nulla nec nisl consectetur, lacinia neque id, accumsan ante. Curabitur et @@ -70,90 +62,145 @@ public class StringDecode { per conubia nostra, per inceptos himenaeos. Suspendisse erat diam, fringilla sed massa sed, posuere viverra orci. Suspendisse tempor libero non gravida efficitur. Vivamus lacinia risus non orci viverra, at consectetur odio laoreet. - Suspendisse potenti. - - Phasellus vel nisi iaculis, accumsan quam sed, bibendum eros. Sed venenatis - nulla tortor, et eleifend urna sodales id. Nullam tempus ac metus sit amet - sollicitudin. Nam sed ex diam. Praesent vitae eros et neque condimentum - consectetur eget non tortor. Praesent bibendum vel felis nec dignissim. - Maecenas a enim diam. Suspendisse quis ligula at nisi accumsan lacinia id - hendrerit sapien. \uFF11Donec aliquam mattis lectus eu ultrices. Duis eu nisl\uFF11 - euismod, blandit mauris vel, \uFF11placerat urna. Etiam malesuada enim purus, - tristique mollis odio blandit quis.\uFF11 Vivamus posuere. \uFF11 - \uFF11 - """.getBytes(charset); - longUtf16StartString = """ - \uFF11 - Lorem ipsum dolor sit amet, \uFF11consectetur adipiscing elit. Aliquam ac sem eu - urna egestas \uFF11placerat. Etiam finibus ipsum nulla, non mattis dolor cursus a. - Nulla \uFF11nec nisl consectetur, lacinia neque id, accumsan ante. Curabitur et - sapien in \uFF11magna porta ultricies. \uFF11Sed vel pellentesque nibh. Pellentesque dictum - dignissim diam eu ultricies. Class aptent taciti sociosqu ad litora torquent - per conubia nostra, per inceptos himenaeos. Suspendisse erat diam, fringilla - sed massa sed, posuere viverra orci. Suspendisse tempor libero non gravida - efficitur. Vivamus lacinia risus non orci viverra, at consectetur odio laoreet. - Suspendisse potenti. - - Phasellus vel nisi iaculis, accumsan quam sed, bibendum eros. Sed venenatis - nulla tortor, et eleifend urna sodales id. Nullam tempus ac metus sit amet - sollicitudin. Nam sed ex diam. Praesent vitae eros et neque condimentum - consectetur eget non tortor. Praesent bibendum vel felis nec dignissim. - Maecenas a enim diam. Suspendisse quis ligula at nisi accumsan lacinia id - hendrerit sapien. Donec aliquam mattis lectus eu ultrices. Duis eu nisl - euismod, blandit mauris vel, placerat urna. Etiam malesuada enim purus, - tristique mollis odio blandit quis. Vivamus posuere. - """.getBytes(charset); - - longLatin1String = """ - a\u00B6\u00F6\u00F6\u00F6\u00F6\u00F6\u00F6\u00F6\u00F6\u00F6\u00F6\u00F6\u00F6\u00F6\u00F6\u00F6 - b\u00F6\u00F6\u00B6\u00F6\u00F6\u00F6\u00F6\u00F6\u00F6\u00F6\u00F6\u00F6\u00F6\u00F6\u00F6\u00F6 - c\u00F6\u00F6\u00F6\u00B6\u00F6\u00F6\u00F6\u00F6\u00F6\u00F6\u00F6\u00F6\u00F6\u00F6\u00F6\u00F6 - d\u00F6\u00F6\u00F6\u00F6\u00B6\u00F6\u00F6\u00F6\u00F6\u00F6\u00F6\u00F6\u00F6\u00F6\u00F6\u00F6 - e\u00F6\u00F6\u00F6\u00F6\u00F6\u00B6\u00F6\u00F6\u00F6\u00F6\u00F6\u00F6\u00F6\u00F6\u00F6\u00F6 - f\u00F6\u00F6\u00F6\u00F6\u00F6\u00F6\u00B6\u00F6\u00F6\u00F6\u00F6\u00F6\u00F6\u00F6\u00F6\u00F6 - g\u00F6\u00F6\u00F6\u00F6\u00F6\u00F6\u00F6\u00B6\u00F6\u00F6\u00F6\u00F6\u00F6\u00F6\u00F6\u00F6 - h\u00F6\u00F6\u00F6\u00F6\u00F6\u00F6\u00F6\u00F6\u00B6\u00F6\u00F6\u00F6\u00F6\u00F6\u00F6\u00F6 - i\u00F6\u00F6\u00F6\u00F6\u00F6\u00F6\u00F6\u00F6\u00F6\u00B6\u00F6\u00F6\u00F6\u00F6\u00F6\u00F6 - j\u00F6\u00F6\u00F6\u00F6\u00F6\u00F6\u00F6\u00F6\u00F6\u00F6\u00B6\u00F6\u00F6\u00F6\u00F6\u00F6 - k\u00F6\u00F6\u00F6\u00F6\u00F6\u00F6\u00F6\u00F6\u00F6\u00F6\u00F6\u00B6\u00F6\u00F6\u00F6\u00F6 - l\u00F6\u00F6\u00F6\u00F6\u00F6\u00F6\u00F6\u00F6\u00F6\u00F6\u00F6\u00F6\u00B6\u00F6\u00F6\u00F6 - m\u00F6\u00F6\u00F6\u00F6\u00F6\u00F6\u00F6\u00F6\u00F6\u00F6\u00F6\u00F6\u00F6\u00B6\u00F6\u00F6 - """.getBytes(charset); + Suspendisse potenti."""; + private static final String UTF16_STRING = "\uFF11".repeat(31); + private static final String LATIN1_STRING = "\u00B6".repeat(31); + + @Setup + public void setup() { + charset = Charset.forName(charsetName); + asciiString = LOREM.substring(0, 32).getBytes(charset); + longAsciiString = LOREM.repeat(200).getBytes(charset); + utf16String = "UTF-\uFF11\uFF16 string".getBytes(charset); + longUtf16EndString = LOREM.repeat(4).concat(UTF16_STRING).getBytes(charset); + longUtf16StartString = UTF16_STRING.concat(LOREM.repeat(4)).getBytes(charset); + longUtf16OnlyString = UTF16_STRING.repeat(10).getBytes(charset); + latin1String = LATIN1_STRING.getBytes(charset); + longLatin1EndString = LOREM.repeat(4).concat(LATIN1_STRING).getBytes(charset); + longLatin1StartString = LATIN1_STRING.concat(LOREM.repeat(4)).getBytes(charset); + longLatin1OnlyString = LATIN1_STRING.repeat(10).getBytes(charset); } @Benchmark - public String decodeAsciiCharsetName() throws Exception { - return new String(asciiString, charsetName); + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public void decodeAsciiShort(Blackhole bh) throws Exception { + bh.consume(new String(asciiString, charset)); + bh.consume(new String(longAsciiString, 0, 15, charset)); + bh.consume(new String(asciiString, 0, 3, charset)); + bh.consume(new String(longAsciiString, 512, 7, charset)); } @Benchmark - public String decodeAscii() throws Exception { - return new String(asciiString, charset); + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public void decodeAsciiLong(Blackhole bh) throws Exception { + bh.consume(new String(longAsciiString, charset)); + bh.consume(new String(longAsciiString, 0, 1024 + 31, charset)); } @Benchmark - public String decodeLatin1Long() throws Exception { - return new String(longLatin1String, charset); + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public void decodeLatin1Short(Blackhole bh) throws Exception { + bh.consume(new String(latin1String, charset)); + bh.consume(new String(latin1String, 0, 15, charset)); + bh.consume(new String(latin1String, 0, 3, charset)); + bh.consume(new String(longLatin1OnlyString, 512, 7, charset)); } @Benchmark - public String decodeUTF16Short() throws Exception { - return new String(utf16String, charset); + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public String decodeLatin1LongStart() throws Exception { + return new String(longLatin1StartString, charset); } @Benchmark + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public String decodeLatin1LongEnd() throws Exception { + return new String(longLatin1EndString, charset); + } + + @Benchmark + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public String decodeLatin1LongOnly() throws Exception { + return new String(longLatin1OnlyString, charset); + } + + @Benchmark + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public void decodeLatin1Mixed(Blackhole bh) throws Exception { + bh.consume(new String(longLatin1EndString, charset)); + bh.consume(new String(longLatin1StartString, charset)); + bh.consume(new String(latin1String, charset)); + bh.consume(new String(longLatin1OnlyString, charset)); + } + + @Benchmark + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public void decodeUTF16Short(Blackhole bh) throws Exception { + bh.consume(new String(utf16String, charset)); + bh.consume(new String(utf16String, 0, 15, charset)); + bh.consume(new String(utf16String, 0, 3, charset)); + bh.consume(new String(utf16String, 0, 7, charset)); + } + + @Benchmark + @CompilerControl(CompilerControl.Mode.DONT_INLINE) public String decodeUTF16LongEnd() throws Exception { - return new String(longUtf16String, charset); + return new String(longUtf16EndString, charset); } @Benchmark + @CompilerControl(CompilerControl.Mode.DONT_INLINE) public String decodeUTF16LongStart() throws Exception { return new String(longUtf16StartString, charset); } @Benchmark - public void decodeUTF16LongMixed(Blackhole bh) throws Exception { + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public String decodeUTF16LongOnly() throws Exception { + return new String(longUtf16OnlyString, charset); + } + + @Benchmark + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public void decodeUTF16Mixed(Blackhole bh) throws Exception { + bh.consume(new String(longUtf16StartString, charset)); + bh.consume(new String(longUtf16EndString, charset)); + bh.consume(new String(utf16String, charset)); + bh.consume(new String(longUtf16OnlyString, charset)); + } + + @Benchmark + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public void decodeAllMixed(Blackhole bh) throws Exception { + bh.consume(new String(utf16String, charset)); + bh.consume(new String(longUtf16EndString, charset)); + bh.consume(new String(utf16String, 0, 15, charset)); bh.consume(new String(longUtf16StartString, charset)); - bh.consume(new String(longUtf16String, charset)); + bh.consume(new String(asciiString, 0, 3, charset)); + bh.consume(new String(longUtf16OnlyString, charset)); + bh.consume(new String(latin1String, charset)); + bh.consume(new String(longLatin1EndString, charset)); + bh.consume(new String(longLatin1StartString, charset)); + bh.consume(new String(latin1String, 0, 7, charset)); + bh.consume(new String(longLatin1OnlyString, charset)); + bh.consume(new String(asciiString, charset)); + bh.consume(new String(longAsciiString, charset)); + } + + @Benchmark + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public void decodeShortMixed(Blackhole bh) throws Exception { + bh.consume(new String(utf16String, 0, 15, charset)); + bh.consume(new String(latin1String, 0, 15, charset)); + bh.consume(new String(asciiString, charset)); + bh.consume(new String(utf16String, charset)); + bh.consume(new String(latin1String, 0, 3, charset)); + bh.consume(new String(asciiString, 0, 3, charset)); + bh.consume(new String(utf16String, 0, 7, charset)); + bh.consume(new String(latin1String, charset)); + bh.consume(new String(asciiString, 0, 7, charset)); + bh.consume(new String(utf16String, 0, 3, charset)); + bh.consume(new String(latin1String, 0, 7, charset)); + bh.consume(new String(asciiString, 0, 15, charset)); } } diff --git a/test/micro/org/openjdk/bench/java/lang/StringEncode.java b/test/micro/org/openjdk/bench/java/lang/StringEncode.java index 6e67d3e8cee74134d593af283bab7e0f9ed180b4..30f5a18450ee7e89c8dfafbfb333649a326d0df3 100644 --- a/test/micro/org/openjdk/bench/java/lang/StringEncode.java +++ b/test/micro/org/openjdk/bench/java/lang/StringEncode.java @@ -30,97 +30,197 @@ import java.util.concurrent.TimeUnit; @BenchmarkMode(Mode.AverageTime) @OutputTimeUnit(TimeUnit.NANOSECONDS) -@Fork(value = 3) -@Warmup(iterations = 5, time = 2) +@Fork(value = 2) +@Warmup(iterations = 5, time = 3) @Measurement(iterations = 5, time = 3) @State(Scope.Thread) public class StringEncode { - @Param({"US-ASCII", "ISO-8859-1", "UTF-8", "MS932", "ISO-8859-6"}) + // Reduced by default to only UTF-8, previous coverage: + // @Param({"US-ASCII", "ISO-8859-1", "UTF-8", "MS932", "ISO-8859-6", "ISO-2022-KR"}) + @Param({"UTF-8"}) private String charsetName; + private Charset charset; private String asciiString; + private String asciiString3; + private String asciiString7; + private String asciiString15; + private String longAsciiString; + private String longAsciiString1055; private String utf16String; - private String longUtf16String; + private String utf16String3; + private String utf16String7; + private String utf16String15; + private String longUtf16EndString; private String longUtf16StartString; + private String longUtf16OnlyString; + private String latin1String; + private String latin1String3; + private String latin1String7; + private String latin1String15; + private String longLatin1EndString; + private String longLatin1StartString; + private String longLatin1OnlyString; + + private static final String LOREM = """ + Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aliquam ac sem eu + urna egestas placerat. Etiam finibus ipsum nulla, non mattis dolor cursus a. + Nulla nec nisl consectetur, lacinia neque id, accumsan ante. Curabitur et + sapien in magna porta ultricies. Sed vel pellentesque nibh. Pellentesque dictum + dignissim diam eu ultricies. Class aptent taciti sociosqu ad litora torquent + per conubia nostra, per inceptos himenaeos. Suspendisse erat diam, fringilla + sed massa sed, posuere viverra orci. Suspendisse tempor libero non gravida + efficitur. Vivamus lacinia risus non orci viverra, at consectetur odio laoreet. + Suspendisse potenti."""; + private static final String UTF16_STRING = "\uFF11".repeat(31); + private static final String LATIN1_STRING = "\u00B6".repeat(31); @Setup public void setup() { charset = Charset.forName(charsetName); - asciiString = "ascii string"; - utf16String = "UTF-\uFF11\uFF16 string"; - longUtf16String = """ - Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aliquam ac sem eu - urna egestas placerat. Etiam finibus ipsum nulla, non mattis dolor cursus a. - Nulla nec nisl consectetur, lacinia neque id, accumsan ante. Curabitur et - sapien in magna porta ultricies. Sed vel pellentesque nibh. Pellentesque dictum - dignissim diam eu ultricies. Class aptent taciti sociosqu ad litora torquent - per conubia nostra, per inceptos himenaeos. Suspendisse erat diam, fringilla - sed massa sed, posuere viverra orci. Suspendisse tempor libero non gravida - efficitur. Vivamus lacinia risus non orci viverra, at consectetur odio laoreet. - Suspendisse potenti. - - Phasellus vel nisi iaculis, accumsan quam sed, bibendum eros. Sed venenatis - nulla tortor, et eleifend urna sodales id. Nullam tempus ac metus sit amet - sollicitudin. Nam sed ex diam. Praesent vitae eros et neque condimentum - consectetur eget non tortor. Praesent bibendum vel felis nec dignissim. - Maecenas a enim diam. Suspendisse quis ligula at nisi accumsan lacinia id - hendrerit sapien. Donec aliquam mattis lectus eu ultrices. Duis eu nisl - euismod, blandit mauris vel, placerat urna. Etiam malesuada enim purus, - tristique mollis odio blandit quis. Vivamus posuere. - \uFF11 - """; - longUtf16StartString = """ - \uFF11 - Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aliquam ac sem eu - urna egestas placerat. Etiam finibus ipsum nulla, non mattis dolor cursus a. - Nulla nec nisl consectetur, lacinia neque id, accumsan ante. Curabitur et - sapien in magna porta ultricies. Sed vel pellentesque nibh. Pellentesque dictum - dignissim diam eu ultricies. Class aptent taciti sociosqu ad litora torquent - per conubia nostra, per inceptos himenaeos. Suspendisse erat diam, fringilla - sed massa sed, posuere viverra orci. Suspendisse tempor libero non gravida - efficitur. Vivamus lacinia risus non orci viverra, at consectetur odio laoreet. - Suspendisse potenti. - - Phasellus vel nisi iaculis, accumsan quam sed, bibendum eros. Sed venenatis - nulla tortor, et eleifend urna sodales id. Nullam tempus ac metus sit amet - sollicitudin. Nam sed ex diam. Praesent vitae eros et neque condimentum - consectetur eget non tortor. Praesent bibendum vel felis nec dignissim. - Maecenas a enim diam. Suspendisse quis ligula at nisi accumsan lacinia id - hendrerit sapien. Donec aliquam mattis lectus eu ultrices. Duis eu nisl - euismod, blandit mauris vel, placerat urna. Etiam malesuada enim purus, - tristique mollis odio blandit quis. Vivamus posuere. - """; + asciiString = LOREM.substring(0, 32); + asciiString3 = LOREM.substring(0, 3); + asciiString7 = LOREM.substring(0, 7); + asciiString15 = LOREM.substring(0, 15); + longAsciiString = LOREM.repeat(200); + longAsciiString1055 = longAsciiString.substring(0, 1055); + utf16String = UTF16_STRING; + utf16String3 = UTF16_STRING.substring(0, 3); + utf16String7 = UTF16_STRING.substring(0, 7); + utf16String15 = UTF16_STRING.substring(0, 15); + longUtf16EndString = LOREM.repeat(4).concat(UTF16_STRING); + longUtf16StartString = UTF16_STRING.concat(LOREM.repeat(4)); + longUtf16OnlyString = UTF16_STRING.repeat(10); + latin1String = LATIN1_STRING; + latin1String3 = LATIN1_STRING.substring(0, 3); + latin1String7 = LATIN1_STRING.substring(0, 7); + latin1String15 = LATIN1_STRING.substring(0, 15); + longLatin1EndString = LOREM.repeat(4).concat(LATIN1_STRING); + longLatin1StartString = LATIN1_STRING.concat(LOREM.repeat(4)); + longLatin1OnlyString = LATIN1_STRING.repeat(10); } @Benchmark - public byte[] encodeAsciiCharsetName() throws Exception { - return asciiString.getBytes(charset); + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public void encodeAsciiShort(Blackhole bh) throws Exception { + bh.consume(asciiString.getBytes(charset)); + bh.consume(asciiString3.getBytes(charset)); + bh.consume(asciiString15.getBytes(charset)); + bh.consume(asciiString7.getBytes(charset)); } @Benchmark - public byte[] encodeAscii() throws Exception { - return asciiString.getBytes(charset); + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public void encodeAsciiLong(Blackhole bh) throws Exception { + bh.consume(longAsciiString.getBytes(charset)); + bh.consume(longAsciiString1055.getBytes(charset)); } @Benchmark - public void encodeMix(Blackhole bh) throws Exception { - bh.consume(asciiString.getBytes(charset)); + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public void encodeUTF16Short(Blackhole bh) throws Exception { bh.consume(utf16String.getBytes(charset)); + bh.consume(utf16String3.getBytes(charset)); + bh.consume(utf16String15.getBytes(charset)); + bh.consume(utf16String7.getBytes(charset)); } @Benchmark + @CompilerControl(CompilerControl.Mode.DONT_INLINE) public byte[] encodeUTF16LongEnd() throws Exception { - return longUtf16String.getBytes(charset); + return longUtf16EndString.getBytes(charset); } @Benchmark + @CompilerControl(CompilerControl.Mode.DONT_INLINE) public byte[] encodeUTF16LongStart() throws Exception { return longUtf16StartString.getBytes(charset); } @Benchmark - public byte[] encodeUTF16() throws Exception { - return utf16String.getBytes(charset); + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public byte[] encodeUTF16LongOnly() throws Exception { + return longUtf16OnlyString.getBytes(charset); + } + + @Benchmark + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public void encodeUTF16Mixed(Blackhole bh) throws Exception { + bh.consume(utf16String.getBytes(charset)); + bh.consume(longUtf16StartString.getBytes(charset)); + bh.consume(longUtf16EndString.getBytes(charset)); + bh.consume(longUtf16OnlyString.getBytes(charset)); + } + + @Benchmark + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public void encodeLatin1Short(Blackhole bh) throws Exception { + bh.consume(latin1String.getBytes(charset)); + bh.consume(latin1String3.getBytes(charset)); + bh.consume(latin1String15.getBytes(charset)); + bh.consume(latin1String7.getBytes(charset)); + } + + @Benchmark + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public byte[] encodeLatin1LongOnly() throws Exception { + return longLatin1OnlyString.getBytes(charset); + } + + @Benchmark + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public byte[] encodeLatin1LongStart() throws Exception { + return longLatin1StartString.getBytes(charset); + } + + @Benchmark + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public byte[] encodeLatin1LongEnd() throws Exception { + return longLatin1EndString.getBytes(charset); + } + + @Benchmark + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public void encodeLatin1Mixed(Blackhole bh) throws Exception { + bh.consume(longLatin1EndString.getBytes(charset)); + bh.consume(longLatin1StartString.getBytes(charset)); + bh.consume(longLatin1OnlyString.getBytes(charset)); + bh.consume(latin1String.getBytes(charset)); + } + + @Benchmark + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public void encodeAllMixed(Blackhole bh) throws Exception { + bh.consume(utf16String.getBytes(charset)); + bh.consume(longUtf16StartString.getBytes(charset)); + bh.consume(asciiString7.getBytes(charset)); + bh.consume(longUtf16EndString.getBytes(charset)); + bh.consume(latin1String3.getBytes(charset)); + bh.consume(longUtf16OnlyString.getBytes(charset)); + bh.consume(longLatin1EndString.getBytes(charset)); + bh.consume(longLatin1StartString.getBytes(charset)); + bh.consume(utf16String15.getBytes(charset)); + bh.consume(longLatin1OnlyString.getBytes(charset)); + bh.consume(latin1String.getBytes(charset)); + bh.consume(asciiString.getBytes(charset)); + bh.consume(longAsciiString.getBytes(charset)); + } + + @Benchmark + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public void encodeShortMixed(Blackhole bh) throws Exception { + bh.consume(utf16String3.getBytes(charset)); + bh.consume(latin1String7.getBytes(charset)); + bh.consume(asciiString15.getBytes(charset)); + bh.consume(utf16String.getBytes(charset)); + bh.consume(latin1String3.getBytes(charset)); + bh.consume(asciiString7.getBytes(charset)); + bh.consume(utf16String15.getBytes(charset)); + bh.consume(latin1String.getBytes(charset)); + bh.consume(asciiString3.getBytes(charset)); + bh.consume(utf16String7.getBytes(charset)); + bh.consume(latin1String15.getBytes(charset)); + bh.consume(asciiString.getBytes(charset)); } } diff --git a/test/micro/org/openjdk/bench/java/util/zip/InflaterInputStreams.java b/test/micro/org/openjdk/bench/java/util/zip/InflaterInputStreams.java new file mode 100644 index 0000000000000000000000000000000000000000..ab6be0e9374e833d6b6597829a72fe286a1c103d --- /dev/null +++ b/test/micro/org/openjdk/bench/java/util/zip/InflaterInputStreams.java @@ -0,0 +1,114 @@ +/* + * Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package org.openjdk.bench.java.util.zip; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Level; +import org.openjdk.jmh.annotations.Measurement; +import org.openjdk.jmh.annotations.Param; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.annotations.Warmup; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.util.Random; +import java.util.concurrent.TimeUnit; +import java.util.zip.Inflater; +import java.util.zip.InflaterInputStream; +import java.util.zip.DeflaterOutputStream; + +/** + * A simple benchmark to measure the performance improvements achieved by avoiding + * unnecessary native calls in InflaterInputStream::read() (see JDK-8281962). + * + * before JDK-8281962 + * ------------------ + * Benchmark (size) Mode Cnt Score Error Units + * InflaterInputStreams.inflaterInputStreamRead 256 avgt 5 2.571 0.120 us/op + * InflaterInputStreams.inflaterInputStreamRead 512 avgt 5 2.861 0.064 us/op + * InflaterInputStreams.inflaterInputStreamRead 4096 avgt 5 5.110 0.278 us/op + * + * after JDK-8281962 + * ----------------- + * Benchmark (size) Mode Cnt Score Error Units + * InflaterInputStreams.inflaterInputStreamRead 256 avgt 5 2.332 0.081 us/op + * InflaterInputStreams.inflaterInputStreamRead 512 avgt 5 2.691 0.293 us/op + * InflaterInputStreams.inflaterInputStreamRead 4096 avgt 5 4.812 1.038 us/op + * + */ +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.MICROSECONDS) +@State(Scope.Thread) +@Warmup(iterations = 3, time = 5, timeUnit = TimeUnit.SECONDS) +@Measurement(iterations = 5, time = 5, timeUnit = TimeUnit.SECONDS) +public class InflaterInputStreams { + + @Param({"256", "512", "4096"}) + private int size; + private byte[] chars; + private byte[] words; + private static byte[] inflated; + ByteArrayInputStream deflated; + + @Setup(Level.Trial) + public void beforeRun() throws IOException { + final int charCount = 64; + final int wordLength = 8; + chars = new byte[charCount]; + Random r = new Random(123456789); + r.nextBytes(chars); + words = new byte[1024]; + for (int i = 0; i < words.length / wordLength; i++) { + System.arraycopy(chars, r.nextInt(charCount - wordLength), words, i * wordLength, wordLength); + } + inflated = new byte[2*size]; + } + + @Setup(Level.Iteration) + public void beforeIteration() throws IOException { + // Maximum deflated size (see https://stackoverflow.com/a/23578269/4146053) + int maxDeflated = size + 5*(size/16383 + 1); + ByteArrayOutputStream baos = new ByteArrayOutputStream(maxDeflated); + DeflaterOutputStream defout = new DeflaterOutputStream(baos); + ByteArrayInputStream bais = new ByteArrayInputStream(words, 0, size); + bais.transferTo(defout); + // We need to close the DeflaterOutputStream in order to flush + // all the compressed data in the Deflater. + defout.close(); + deflated = new ByteArrayInputStream(baos.toByteArray()); + } + + @Benchmark + public void inflaterInputStreamRead() throws IOException { + deflated.reset(); + InflaterInputStream iis = new InflaterInputStream(deflated); + while (iis.read(inflated, 0, inflated.length) != -1); + } +} diff --git a/test/micro/org/openjdk/bench/vm/compiler/LeaInstruction.java b/test/micro/org/openjdk/bench/vm/compiler/LeaInstruction.java new file mode 100644 index 0000000000000000000000000000000000000000..02b10d7ddf71e177a593312e25b7389648f3117f --- /dev/null +++ b/test/micro/org/openjdk/bench/vm/compiler/LeaInstruction.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.vm.compiler; + +import org.openjdk.jmh.annotations.*; +import org.openjdk.jmh.infra.Blackhole; + +import java.util.concurrent.TimeUnit; + +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +@Fork(value = 1, jvmArgsAppend = {"-XX:LoopUnrollLimit=1"}) +@State(Scope.Thread) +public class LeaInstruction { + static final int ITERATION = 1000; + + int x, y; + + @Benchmark + public void IS_D_int(Blackhole bh) { + int x = this.x; + for (int i = 0; i < ITERATION; i++) { + x = x * 4 + 10; + } + bh.consume(x); + } + + @Benchmark + public void B_I_D_int(Blackhole bh) { + int x = this.x, y = this.y; + for (int i = 0; i < ITERATION; i++) { + x = x + y + 10; + y = x + y + 20; + } + bh.consume(x); + bh.consume(y); + } + + @Benchmark + public void B_IS_int(Blackhole bh) { + int x = this.x, y = this.y; + for (int i = 0; i < ITERATION; i++) { + x = x + y * 4; + y = x + y * 8; + } + bh.consume(x); + bh.consume(y); + } + + @Benchmark + public void B_IS_D_int(Blackhole bh) { + int x = this.x, y = this.y; + for (int i = 0; i < ITERATION; i++) { + x = x + y * 4 + 10; + y = x + y * 8 + 20; + } + bh.consume(x); + bh.consume(y); + } + + @Benchmark + public void IS_D_long(Blackhole bh) { + long x = this.x; + for (int i = 0; i < ITERATION; i++) { + x = x * 4 + 10; + } + bh.consume(x); + } + + @Benchmark + public void B_I_D_long(Blackhole bh) { + long x = this.x, y = this.y; + for (int i = 0; i < ITERATION; i++) { + x = x + y + 10; + y = x + y + 20; + } + bh.consume(x); + bh.consume(y); + } + + @Benchmark + public void B_IS_long(Blackhole bh) { + long x = this.x, y = this.y; + for (int i = 0; i < ITERATION; i++) { + x = x + y * 4; + y = x + y * 8; + } + bh.consume(x); + bh.consume(y); + } + + @Benchmark + public void B_IS_D_long(Blackhole bh) { + long x = this.x, y = this.y; + for (int i = 0; i < ITERATION; i++) { + x = x + y * 4 + 10; + y = x + y * 8 + 20; + } + bh.consume(x); + bh.consume(y); + } +} diff --git a/test/micro/org/openjdk/bench/vm/compiler/VectorShiftRight.java b/test/micro/org/openjdk/bench/vm/compiler/VectorShiftRight.java new file mode 100644 index 0000000000000000000000000000000000000000..068d1bd704dba48363d6e8da111a7223cf2a74b6 --- /dev/null +++ b/test/micro/org/openjdk/bench/vm/compiler/VectorShiftRight.java @@ -0,0 +1,129 @@ +/* + * 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 org.openjdk.bench.vm.compiler; + +import org.openjdk.jmh.annotations.*; +import org.openjdk.jmh.infra.*; + +import java.util.concurrent.TimeUnit; +import java.util.Random; + +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +@State(Scope.Thread) +public class VectorShiftRight { + @Param({"1024"}) + public int SIZE; + + private byte[] bytesA, bytesB; + private short[] shortsA, shortsB; + private char[] charsA, charsB; + private int[] intsA, intsB; + private long[] longsA, longsB; + + @Param("0") + private int seed; + private Random r = new Random(seed); + + @Param("3") + private int shiftCount; + + @Setup + public void init() { + bytesA = new byte[SIZE]; + shortsA = new short[SIZE]; + charsA = new char[SIZE]; + intsA = new int[SIZE]; + longsA = new long[SIZE]; + + bytesB = new byte[SIZE]; + shortsB = new short[SIZE]; + charsB = new char[SIZE]; + intsB = new int[SIZE]; + longsB = new long[SIZE]; + + for (int i = 0; i < SIZE; i++) { + bytesA[i] = (byte) r.nextInt(); + shortsA[i] = (short) r.nextInt(); + charsA[i] = (char) r.nextInt(); + intsA[i] = r.nextInt(); + longsA[i] = r.nextLong(); + } + } + + @Benchmark + public void rShiftByte() { + for (int i = 0; i < SIZE; i++) { + bytesB[i] = (byte) (bytesA[i] >> shiftCount); + } + } + + @Benchmark + public void urShiftByte() { + for (int i = 0; i < SIZE; i++) { + bytesB[i] = (byte) (bytesA[i] >>> shiftCount); + } + } + + @Benchmark + public void rShiftShort() { + for (int i = 0; i < SIZE; i++) { + shortsB[i] = (short) (shortsA[i] >> shiftCount); + } + } + + @Benchmark + public void urShiftChar() { + for (int i = 0; i < SIZE; i++) { + charsB[i] = (char) (charsA[i] >>> shiftCount); + } + } + + @Benchmark + public void rShiftInt() { + for (int i = 0; i < SIZE; i++) { + intsB[i] = intsA[i] >> shiftCount; + } + } + + @Benchmark + public void urShiftInt() { + for (int i = 0; i < SIZE; i++) { + intsB[i] = intsA[i] >>> shiftCount; + } + } + + @Benchmark + public void rShiftLong() { + for (int i = 0; i < SIZE; i++) { + longsB[i] = longsA[i] >> shiftCount; + } + } + + @Benchmark + public void urShiftLong() { + for (int i = 0; i < SIZE; i++) { + longsB[i] = longsA[i] >>> shiftCount; + } + } +} diff --git a/test/micro/org/openjdk/bench/vm/gc/MicroLargePages.java b/test/micro/org/openjdk/bench/vm/gc/MicroLargePages.java new file mode 100644 index 0000000000000000000000000000000000000000..67702cfe607473536bf08316733aed234f2891a1 --- /dev/null +++ b/test/micro/org/openjdk/bench/vm/gc/MicroLargePages.java @@ -0,0 +1,62 @@ +// +// 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.vm.gc; + +import java.util.Arrays; +import java.util.concurrent.TimeUnit; +import org.openjdk.jmh.annotations.*; + +@OutputTimeUnit(TimeUnit.MINUTES) +@State(Scope.Thread) +@Fork(jvmArgsAppend = {"-Xmx256m", "-XX:+UseLargePages", "-XX:LargePageSizeInBytes=1g", "-Xlog:pagesize"}, value = 5) + +public class MicroLargePages { + + @Param({"2097152"}) + public int ARRAYSIZE; + + @Param({"1", "2", "4"}) + public int NUM; + + public long[][] INP; + public long[][] OUT; + + @Setup(Level.Trial) + public void BmSetup() { + INP = new long[NUM][ARRAYSIZE]; + OUT = new long[NUM][ARRAYSIZE]; + for (int i = 0; i < NUM; i++) { + Arrays.fill(INP[i], 10); + } + } + + @Benchmark + public void micro_HOP_DIST_4KB() { + for (int i = 0; i < NUM; i += 1) { + for (int j = 0; j < ARRAYSIZE; j += 512) { + OUT[i][j] = INP[i][j]; + } + } + } +}